From 8c9b64914c0d5b28f5e791c3bff0db600d31da14 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Sun, 2 Nov 2025 20:41:19 +0000 Subject: [PATCH 1/3] Add http-1x examples for server SDK usage This commit updates examples to demonstrate server SDK usage with both http@0.2.x and http@1.x, supporting the http-1x migration effort. ## Changes ### New Directories - **legacy/**: Complete set of examples using http@0.2.x/hyper@0.14 with aws-smithy-legacy-http-server. These examples preserve the original behavior for users not yet ready to migrate. - **pokemon-service-server-skd-patch/**: Compatibility layer and patches for bridging http@0 and http@1 types in server SDK. ### Updated Examples Modified existing examples to use http@1.x/hyper@1.x: - pokemon-service: Main service example updated for http@1 - pokemon-service-tls: TLS example with hyper 1.x compatibility - pokemon-service-lambda: Lambda example updated for http@1 - pokemon-service-client-usage: Client examples updated - pokemon-service-common: Common utilities updated ### Key Updates - Cargo.toml files updated with http@1.x and hyper@1.x dependencies - Server initialization code updated for hyper 1.x API changes - Test helpers updated to support both HTTP versions - Connector and middleware examples updated for new hyper API Relates to #3362 --- .changelog/1762114944.md | 14 + examples/legacy/.gitignore | 3 + examples/legacy/Cargo.toml | 15 + examples/legacy/Makefile | 44 + examples/legacy/README.md | 179 ++ .../pokemon-service-client-usage/Cargo.toml | 39 + .../pokemon-service-client-usage/README.md | 49 + .../examples/client-connector.rs | 74 + .../custom-header-using-interceptor.rs | 157 ++ .../examples/custom-header.rs | 62 + .../examples/endpoint-resolver.rs | 102 + .../examples/handling-errors.rs | 130 ++ .../examples/mock-request.rs | 76 + .../examples/response-header-interceptor.rs | 162 ++ .../examples/retry-classifier.rs | 112 + .../examples/retry-customize.rs | 60 + .../examples/simple-client.rs | 53 + .../examples/timeout-config.rs | 64 + .../examples/trace-serialize.rs | 126 ++ .../examples/use-config-bag.rs | 140 ++ .../pokemon-service-client-usage/src/lib.rs | 19 + .../legacy/pokemon-service-common/Cargo.toml | 27 + .../legacy/pokemon-service-common/src/lib.rs | 378 ++++ .../tests/plugins_execution_order.rs | 121 + .../legacy/pokemon-service-lambda/Cargo.toml | 23 + .../legacy/pokemon-service-lambda/src/lib.rs | 32 + .../legacy/pokemon-service-lambda/src/main.rs | 46 + .../tests/fixtures/example-apigw-request.json | 89 + .../legacy/pokemon-service-tls/Cargo.toml | 41 + .../legacy/pokemon-service-tls/src/lib.rs | 13 + .../legacy/pokemon-service-tls/src/main.rs | 191 ++ .../pokemon-service-tls/tests/common/mod.rs | 81 + .../tests/custom_connectors.rs | 29 + .../tests/testdata/localhost.crt | 30 + .../tests/testdata/localhost.key | 52 + examples/legacy/pokemon-service/Cargo.toml | 37 + examples/legacy/pokemon-service/src/authz.rs | 219 ++ examples/legacy/pokemon-service/src/lib.rs | 59 + examples/legacy/pokemon-service/src/main.rs | 115 + examples/legacy/pokemon-service/src/plugin.rs | 81 + .../pokemon-service/tests/common/mod.rs | 33 + .../pokemon-service/tests/event_streaming.rs | 162 ++ .../legacy/pokemon-service/tests/simple.rs | 128 ++ .../pokemon-service-client-usage/Cargo.toml | 17 +- .../examples/client-connector.rs | 33 +- .../examples/mock-request.rs | 2 +- examples/pokemon-service-common/Cargo.toml | 5 +- examples/pokemon-service-common/src/lib.rs | 8 +- .../tests/plugins_execution_order.rs | 2 +- examples/pokemon-service-lambda/Cargo.toml | 8 +- examples/pokemon-service-lambda/src/main.rs | 2 +- .../Cargo.toml | 63 + .../src/constrained.rs | 16 + .../src/error.rs | 885 ++++++++ .../src/event_stream_serde.rs | 202 ++ .../src/hyper_compat.rs | 27 + .../src/input.rs | 618 ++++++ .../src/lib.rs | 317 +++ .../src/model.rs | 578 +++++ .../src/operation.rs | 639 ++++++ .../src/operation_shape.rs | 289 +++ .../src/output.rs | 461 ++++ .../src/protocol_serde.rs | 58 + .../protocol_serde/shape_capture_pokemon.rs | 226 ++ .../shape_capture_pokemon_input.rs | 29 + .../protocol_serde/shape_capturing_payload.rs | 90 + .../src/protocol_serde/shape_check_health.rs | 54 + .../src/protocol_serde/shape_do_nothing.rs | 56 + .../protocol_serde/shape_do_nothing_output.rs | 20 + .../src/protocol_serde/shape_flavor_text.rs | 13 + .../shape_get_pokemon_species.rs | 136 ++ .../shape_get_pokemon_species_input.rs | 12 + .../shape_get_pokemon_species_output.rs | 35 + .../shape_get_server_statistics.rs | 55 + .../shape_get_server_statistics_output.rs | 23 + .../src/protocol_serde/shape_get_storage.rs | 163 ++ .../protocol_serde/shape_get_storage_input.rs | 22 + .../shape_get_storage_output.rs | 29 + .../shape_invalid_pokeball_error.rs | 23 + .../shape_master_ball_unsuccessful.rs | 72 + .../shape_resource_not_found_exception.rs | 23 + .../shape_storage_access_not_authorized.rs | 20 + .../shape_stream_pokemon_radio.rs | 51 + .../shape_stream_pokemon_radio_output.rs | 9 + .../protocol_serde/shape_throttling_error.rs | 17 + .../shape_unsupported_region_error.rs | 23 + .../shape_validation_exception.rs | 35 + .../shape_validation_exception_field.rs | 13 + .../src/service.rs | 1963 +++++++++++++++++ .../src/types.rs | 13 + examples/pokemon-service-tls/Cargo.toml | 22 +- examples/pokemon-service-tls/src/main.rs | 128 +- .../pokemon-service-tls/tests/common/mod.rs | 118 +- .../tests/custom_connectors.rs | 17 +- examples/pokemon-service/Cargo.toml | 16 +- examples/pokemon-service/src/main.rs | 19 +- examples/pokemon-service/tests/common/mod.rs | 62 +- .../pokemon-service/tests/event_streaming.rs | 8 +- examples/pokemon-service/tests/simple.rs | 35 +- 99 files changed, 11343 insertions(+), 204 deletions(-) create mode 100644 .changelog/1762114944.md create mode 100644 examples/legacy/.gitignore create mode 100644 examples/legacy/Cargo.toml create mode 100644 examples/legacy/Makefile create mode 100644 examples/legacy/README.md create mode 100644 examples/legacy/pokemon-service-client-usage/Cargo.toml create mode 100644 examples/legacy/pokemon-service-client-usage/README.md create mode 100644 examples/legacy/pokemon-service-client-usage/examples/client-connector.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/custom-header.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/endpoint-resolver.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/handling-errors.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/mock-request.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/response-header-interceptor.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/retry-classifier.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/retry-customize.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/simple-client.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/timeout-config.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/trace-serialize.rs create mode 100644 examples/legacy/pokemon-service-client-usage/examples/use-config-bag.rs create mode 100644 examples/legacy/pokemon-service-client-usage/src/lib.rs create mode 100644 examples/legacy/pokemon-service-common/Cargo.toml create mode 100644 examples/legacy/pokemon-service-common/src/lib.rs create mode 100644 examples/legacy/pokemon-service-common/tests/plugins_execution_order.rs create mode 100644 examples/legacy/pokemon-service-lambda/Cargo.toml create mode 100644 examples/legacy/pokemon-service-lambda/src/lib.rs create mode 100644 examples/legacy/pokemon-service-lambda/src/main.rs create mode 100644 examples/legacy/pokemon-service-lambda/tests/fixtures/example-apigw-request.json create mode 100644 examples/legacy/pokemon-service-tls/Cargo.toml create mode 100644 examples/legacy/pokemon-service-tls/src/lib.rs create mode 100644 examples/legacy/pokemon-service-tls/src/main.rs create mode 100644 examples/legacy/pokemon-service-tls/tests/common/mod.rs create mode 100644 examples/legacy/pokemon-service-tls/tests/custom_connectors.rs create mode 100644 examples/legacy/pokemon-service-tls/tests/testdata/localhost.crt create mode 100644 examples/legacy/pokemon-service-tls/tests/testdata/localhost.key create mode 100644 examples/legacy/pokemon-service/Cargo.toml create mode 100644 examples/legacy/pokemon-service/src/authz.rs create mode 100644 examples/legacy/pokemon-service/src/lib.rs create mode 100644 examples/legacy/pokemon-service/src/main.rs create mode 100644 examples/legacy/pokemon-service/src/plugin.rs create mode 100644 examples/legacy/pokemon-service/tests/common/mod.rs create mode 100644 examples/legacy/pokemon-service/tests/event_streaming.rs create mode 100644 examples/legacy/pokemon-service/tests/simple.rs create mode 100644 examples/pokemon-service-server-skd-patch/Cargo.toml create mode 100644 examples/pokemon-service-server-skd-patch/src/constrained.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/error.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/hyper_compat.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/input.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/lib.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/model.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/operation.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/operation_shape.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/service.rs create mode 100644 examples/pokemon-service-server-skd-patch/src/types.rs diff --git a/.changelog/1762114944.md b/.changelog/1762114944.md new file mode 100644 index 00000000000..a69ccd4997f --- /dev/null +++ b/.changelog/1762114944.md @@ -0,0 +1,14 @@ +--- +applies_to: +- server +authors: +- drganjoo +references: +- smithy-rs#3362 +breaking: false +new_feature: true +bug_fix: false +--- +Add http-1x examples demonstrating server SDK usage with both http@0.2.x and http@1.x + + Adds legacy examples for http@0 and updated examples for http@1 with hyper 1.x compatibility. diff --git a/examples/legacy/.gitignore b/examples/legacy/.gitignore new file mode 100644 index 00000000000..aaf1fa215c8 --- /dev/null +++ b/examples/legacy/.gitignore @@ -0,0 +1,3 @@ +pokemon-service-client/ +pokemon-service-server-sdk/ +Cargo.lock diff --git a/examples/legacy/Cargo.toml b/examples/legacy/Cargo.toml new file mode 100644 index 00000000000..a374adf6f0e --- /dev/null +++ b/examples/legacy/Cargo.toml @@ -0,0 +1,15 @@ +# Without this configuration, the workspace will be read from `rust-runtime`, causing the build to fail. +[workspace] +resolver = "2" +members = [ + "pokemon-service-common", + "pokemon-service", + "pokemon-service-tls", + "pokemon-service-lambda", + "pokemon-service-server-sdk", + "pokemon-service-client", + "pokemon-service-client-usage", +] + +[profile.release] +lto = true diff --git a/examples/legacy/Makefile b/examples/legacy/Makefile new file mode 100644 index 00000000000..adaf8d22edd --- /dev/null +++ b/examples/legacy/Makefile @@ -0,0 +1,44 @@ +SRC_DIR := $(shell git rev-parse --show-toplevel) +CUR_DIR := $(shell pwd) +GRADLE := $(SRC_DIR)/gradlew +SERVER_SDK_DST := $(CUR_DIR)/pokemon-service-server-sdk +CLIENT_SDK_DST := $(CUR_DIR)/pokemon-service-client +SERVER_SDK_SRC := $(SRC_DIR)/codegen-server-test/build/smithyprojections/codegen-server-test/pokemon-service-server-sdk-http0x/rust-server-codegen +CLIENT_SDK_SRC := $(SRC_DIR)/codegen-client-test/build/smithyprojections/codegen-client-test/pokemon-service-client-http0x/rust-client-codegen + +all: codegen + +codegen: + $(GRADLE) --project-dir $(SRC_DIR) -P modules='pokemon-service-server-sdk-http0x,pokemon-service-client-http0x' :codegen-client-test:assemble :codegen-server-test:assemble + mkdir -p $(SERVER_SDK_DST) $(CLIENT_SDK_DST) + cp -av $(SERVER_SDK_SRC)/* $(SERVER_SDK_DST)/ + cp -av $(CLIENT_SDK_SRC)/* $(CLIENT_SDK_DST)/ + +build: codegen + cargo build + +run: codegen + cargo run + +clippy: codegen + cargo clippy + +test: codegen + cargo test + +doc-open: codegen + cargo doc --no-deps --open + +clean: + cargo clean || echo "Unable to run cargo clean" + +lambda_watch: + cargo lambda watch + +lambda_invoke: + cargo lambda invoke pokemon-service-lambda --data-file pokemon-service/tests/fixtures/example-apigw-request.json + +distclean: clean + rm -rf $(SERVER_SDK_DST) $(CLIENT_SDK_DST) Cargo.lock + +.PHONY: all diff --git a/examples/legacy/README.md b/examples/legacy/README.md new file mode 100644 index 00000000000..2e7140b8fb2 --- /dev/null +++ b/examples/legacy/README.md @@ -0,0 +1,179 @@ +# Legacy HTTP 0.x Examples + +This directory contains examples for Smithy-rs using HTTP 0.x (hyper 0.14, http 0.2). These examples use the legacy HTTP stack with `aws-smithy-legacy-http` and `aws-smithy-legacy-http-server`. + +For HTTP 1.x examples (hyper 1.x, http 1.x), see the parent [examples](../) directory. + +## Building + +### 1. Generate the SDKs + +From this directory, run: + +```bash +make codegen +``` + +This will generate: +- `pokemon-service-server-sdk-http0x` - Server SDK using HTTP 0.x +- `pokemon-service-client-http0x` - Client SDK using HTTP 0.x + +The generated SDKs are copied to: +- `pokemon-service-server-sdk/` +- `pokemon-service-client/` + +### 2. Build all examples + +```bash +cargo build +``` + +Or to check without building artifacts: + +```bash +cargo check +``` + +## Running the Examples + +### Start the Pokemon Service + +In one terminal, start the server: + +```bash +cargo run --bin pokemon-service +``` + +The server will start on `http://localhost:13734` + +### Run Client Examples + +In another terminal, from the `pokemon-service-client-usage/` directory: + +```bash +cd pokemon-service-client-usage +cargo run --example simple-client +``` + +#### Available Client Examples + +| Example | Description | +|---------|-------------| +| `simple-client` | Basic client usage - creates a client and calls an operation | +| `endpoint-resolver` | Custom endpoint resolver configuration | +| `handling-errors` | Sending input parameters and handling errors | +| `custom-header` | Adding custom headers to requests | +| `custom-header-using-interceptor` | Accessing operation name in an interceptor | +| `response-header-interceptor` | Getting operation name and accessing response before deserialization | +| `use-config-bag` | Using the property bag to pass data across interceptors | +| `retry-customize` | Customizing retry settings | +| `timeout-config` | Configuring timeouts | +| `mock-request` | Using custom HttpConnector for mock responses | +| `trace-serialize` | Tracing request/response during serialization | +| `client-connector` | Changing TLS configuration | + +To list all available examples: + +```bash +cd pokemon-service-client-usage +cargo run --example +``` + +### Other Services + +#### Pokemon Service with TLS + +```bash +cargo run --bin pokemon-service-tls +``` + +#### Pokemon Service on AWS Lambda + +```bash +cargo run --bin pokemon-service-lambda +``` + +## Project Structure + +``` +legacy/ +├── pokemon-service/ # Main HTTP service implementation +├── pokemon-service-tls/ # TLS-enabled service +├── pokemon-service-lambda/ # AWS Lambda service +├── pokemon-service-common/ # Shared service logic +├── pokemon-service-client-usage/ # Client usage examples +├── pokemon-service-server-sdk/ # Generated server SDK (HTTP 0.x) +└── pokemon-service-client/ # Generated client SDK (HTTP 0.x) +``` + +## Key Dependencies (HTTP 0.x) + +- `hyper = "0.14"` +- `http = "0.2"` +- `aws-smithy-legacy-http` +- `aws-smithy-legacy-http-server` + +## Regenerating SDKs + +If you need to regenerate the SDKs from scratch: + +```bash +rm -rf pokemon-service-server-sdk pokemon-service-client +make codegen +``` + +## Testing + +Run all tests: + +```bash +cargo test +``` + +Run tests for a specific package: + +```bash +cargo test -p pokemon-service +``` + +## Troubleshooting + +### Port Already in Use + +If port 13734 is already in use, you can specify a different port: + +```bash +cargo run --bin pokemon-service -- --port 8080 +``` + +Then update the client examples to use the new port by setting the environment variable: + +```bash +POKEMON_SERVICE_URL=http://localhost:8080 cargo run --example simple-client +``` + +### SDK Generation Issues + +If the generated SDKs have issues, try cleaning and regenerating: + +```bash +# Clean generated SDKs +rm -rf pokemon-service-server-sdk pokemon-service-client + +# Clean gradle cache +cd ../.. +./gradlew clean + +# Regenerate +cd examples/legacy +make codegen +``` + +## Migration to HTTP 1.x + +For new projects, we recommend using the HTTP 1.x examples in the parent [examples](../) directory. These legacy examples are maintained for backward compatibility and for projects that need to use the HTTP 0.x stack. + +The main differences: +- HTTP 1.x uses `hyper 1.x`, `http 1.x` +- HTTP 1.x uses `aws-smithy-http`, `aws-smithy-http-server` (not legacy versions) +- HTTP 1.x has better performance and modern async runtime support diff --git a/examples/legacy/pokemon-service-client-usage/Cargo.toml b/examples/legacy/pokemon-service-client-usage/Cargo.toml new file mode 100644 index 00000000000..fe942c0e9fd --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "pokemon-service-client-usage" +version = "0.1.0" +edition = "2021" +publish = false + +[features] + + +[dependencies] +# The generated client utilizes types defined in other crates, such as `aws_smithy_types` +# and `aws_smithy_http`. However, most of these types are re-exported by the generated client, +# eliminating the need to directly depend on the crates that provide them. In rare instances, +# you may still need to include one of these crates as a dependency. Examples that require this +# are specifically noted in comments above the corresponding dependency in this file. +pokemon-service-client = { path = "../pokemon-service-client/", package = "pokemon-service-client-http0x", features = ["behavior-version-latest"] } + +# Required for getting the operation name from the `Metadata`. +aws-smithy-legacy-http = { path = "../../../rust-runtime/aws-smithy-legacy-http/" } + +# Required for `Storable` and `StoreReplace` in `response-header-interceptor` example. +aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types/" } + +# Required for `HyperClientBuilder` in `client-connector` example. +aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime/", features=["test-util"] } + +# Required for `Metadata` in `custom-header-using-interceptor` example. +aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api/", features=["client"] } + + +hyper = { version = "0.14.25", features = ["client", "full"] } +tokio = {version = "1.26.0", features=["full"]} +tracing = "0.1.37" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } +rustls = "0.21.8" +hyper-rustls = "0.24.1" +http = "0.2.9" +uuid = {version="1.4.1", features = ["v4"]} +thiserror = "1.0.49" diff --git a/examples/legacy/pokemon-service-client-usage/README.md b/examples/legacy/pokemon-service-client-usage/README.md new file mode 100644 index 00000000000..08021c37e82 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/README.md @@ -0,0 +1,49 @@ +# smithy-rs Client Examples + +This package contains some examples on how to use the Smithy Client to communicate +with a Smithy-based service. + +## Pre-requisites + +1. Build the `pokemon-service-client` and `pokemon-service` by invoking `make` in the + [examples](https://github.com/smithy-lang/smithy-rs/tree/main/examples) folder. + +```console +make +``` + +2. Run the Pokemon service locally by issuing the following command from the + [examples](https://github.com/smithy-lang/smithy-rs/tree/main/examples) folder. This + will launch the Smithy-Rs based service on TCP port 13734. + +```console +cargo run --bin pokemon-service +``` + +## Running the examples + +You can view a list of examples by running `cargo run --example` from the +[pokemon-service-client-usage](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage) +folder. To run an example, pass its name to the `cargo run --example` command, e.g.: + +```console +cargo run --example simple-client +``` + +## List of examples + +| Rust Example | Description | +|--------------------------------|-------------------------------------------------------------------------| +| simple-client | Creates a Smithy Client and calls an operation on it. | +| endpoint-resolver | How to set a custom endpoint resolver. | +| handling-errors | How to send an input parameter to an operation, and to handle errors. | +| custom-header | How to add headers to a request. | +| custom-header-using-interceptor| How to access operation name being called in an interceptor. | +| response-header-interceptor | How to get operation name and access response before it is deserialized.| +| use-config-bag | How to use the property bag to pass data across interceptors. | +| retries-customize | Customize retry settings. | +| retries-disable | How to disable retries. | +| timeout-config | How to configure timeouts. | +| mock-request | Use a custom HttpConnector / Client to generate mock responses. | +| trace-serialize | Trace request and response as they are serialized / deserialized. | +| client-connector | Shows how to change TLS related configuration. | diff --git a/examples/legacy/pokemon-service-client-usage/examples/client-connector.rs b/examples/legacy/pokemon-service-client-usage/examples/client-connector.rs new file mode 100644 index 00000000000..b1a7ecef846 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/client-connector.rs @@ -0,0 +1,74 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to set connector settings. For example, how to set +/// trusted root certificates to use for HTTPs communication. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example client-connector`. +/// +use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; +use hyper_rustls::ConfigBuilderExt; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + let tls_config = rustls::ClientConfig::builder() + .with_safe_defaults() + // `with_native_roots()`: Load platform trusted root certificates. + // `with_webpki_roots()`: Load Mozilla’s set of trusted roots. + .with_native_roots() + // To use client side certificates, you can use + // `.with_client_auth_cert(client_cert, client_key)` instead of `.with_no_client_auth()` + .with_no_client_auth(); + + let tls_connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(tls_config) + // This can be changed to `.https_only()` to ensure that the client always uses HTTPs + .https_or_http() + .enable_http1() + .enable_http2() + .build(); + + // Create a hyper-based HTTP client that uses this TLS connector. + let http_client = HyperClientBuilder::new().build(tls_connector); + + // Pass the smithy connector to the Client::ConfigBuilder + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + // Instantiate a client by applying the configuration. + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(?response, "Response from service") +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs b/examples/legacy/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs new file mode 100644 index 00000000000..00878beb5eb --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/custom-header-using-interceptor.rs @@ -0,0 +1,157 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// In this example, a custom header `x-amzn-client-ttl-seconds` is set for all outgoing requests. +/// It serves as a demonstration of how an operation name can be retrieved and utilized within +/// the interceptor. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example custom-header-using-interceptor`. +/// +use std::{collections::HashMap, time::Duration}; + +use aws_smithy_runtime_api::client::orchestrator::Metadata; +use pokemon_service_client::config::{ConfigBag, Intercept}; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client::{ + config::{interceptors::BeforeTransmitInterceptorContextMut, RuntimeComponents}, + error::BoxError, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +// The `TtlHeaderInterceptor` keeps a map of operation specific value to send +// in the header for each Request. +#[derive(Debug)] +pub struct TtlHeaderInterceptor { + /// Default time-to-live for an operation. + default_ttl: hyper::http::HeaderValue, + /// Operation specific time-to-live. + operation_ttl: HashMap<&'static str, hyper::http::HeaderValue>, +} + +// Helper function to format duration as fractional seconds. +fn format_ttl_value(ttl: Duration) -> String { + format!("{:.2}", ttl.as_secs_f64()) +} + +impl TtlHeaderInterceptor { + fn new(default_ttl: Duration) -> Self { + let duration_str = format_ttl_value(default_ttl); + let default_ttl_value = hyper::http::HeaderValue::from_str(duration_str.as_str()) + .expect("could not create a header value for the default ttl"); + + Self { + default_ttl: default_ttl_value, + operation_ttl: Default::default(), + } + } + + /// Adds an operation name specific timeout value that needs to be set in the header. + fn add_operation_ttl(&mut self, operation_name: &'static str, ttl: Duration) { + let duration_str = format_ttl_value(ttl); + + self.operation_ttl.insert( + operation_name, + hyper::http::HeaderValue::from_str(duration_str.as_str()) + .expect("cannot create header value for the given ttl duration"), + ); + } +} + +/// Appends the header `x-amzn-client-ttl-seconds` using either the default time-to-live value +/// or an operation-specific value if it was set earlier using `add_operation_ttl`. +//impl aws_smithy_runtime_api::client::interceptors::Interceptor for TtlHeaderInterceptor { +impl Intercept for TtlHeaderInterceptor { + fn name(&self) -> &'static str { + "TtlHeaderInterceptor" + } + + /// Before the request is signed, add the header to the outgoing request. + fn modify_before_signing( + &self, + context: &mut BeforeTransmitInterceptorContextMut<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Metadata in the ConfigBag has the operation name. + let metadata = cfg.load::().expect("metadata should exist"); + let operation_name = metadata.name(); + + // Get operation specific or default HeaderValue to set for the header key. + let ttl = self + .operation_ttl + .get(operation_name) + .unwrap_or(&self.default_ttl); + + context + .request_mut() + .headers_mut() + .insert("x-amzn-client-ttl-seconds", ttl.clone()); + + tracing::info!("{operation_name} header set to {ttl:?}"); + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default set the value of all operations to 6 seconds. + const DEFAULT_TTL: Duration = Duration::from_secs(6); + + // Set up the interceptor to add an operation specific value of 3.5 seconds to be added + // for GetStorage operation. + let mut ttl_headers_interceptor = TtlHeaderInterceptor::new(DEFAULT_TTL); + ttl_headers_interceptor.add_operation_ttl("GetStorage", Duration::from_millis(3500)); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(ttl_headers_interceptor) + .build(); + + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response for get_server_statistics()"); + + // Call the operation `get_storage` on the Pokémon service. The `TtlHeaderInterceptor` + // interceptor will add a specific header name / value pair for this operation. + let response = client + .get_storage() + .user("ash") + .passcode("pikachu123") + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/custom-header.rs b/examples/legacy/pokemon-service-client-usage/examples/custom-header.rs new file mode 100644 index 00000000000..d84432f68c2 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/custom-header.rs @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` client, and call an operation with custom +/// headers in the request. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example custom-header` +/// +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Apply the configuration on the client, and return that. + pokemon_service_client::Client::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .customize() + .mutate_request(|req| { + // For demonstration purposes, add a header `x-ttl-seconds` to the outgoing request. + let headers = req.headers_mut(); + headers.insert( + hyper::header::HeaderName::from_static("x-ttl-seconds"), + hyper::header::HeaderValue::from(30), + ); + }) + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/endpoint-resolver.rs b/examples/legacy/pokemon-service-client-usage/examples/endpoint-resolver.rs new file mode 100644 index 00000000000..565efb18acd --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/endpoint-resolver.rs @@ -0,0 +1,102 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how a custom `ResolveEndpoint` can be implemented for resolving +/// endpoint of a request. Additionally, it shows how a header can be added using the endpoint +/// builder. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example endpoint-resolver`. +/// +use pokemon_service_client::config::endpoint::{Endpoint, EndpointFuture, Params, ResolveEndpoint}; +use pokemon_service_client::primitives::{DateTime, DateTimeFormat}; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::setup_tracing_subscriber; + +use std::time::SystemTime; + +// This struct, provided as an example, constructs the URL that should be set on each request during initialization. +// It also implements the `ResolveEndpoint` trait, enabling it to be assigned as the endpoint_resolver in the `Config`. +#[derive(Debug)] +struct RegionalEndpoint { + url_to_use: String, +} + +impl RegionalEndpoint { + fn new(regional_url: &str, port: u16) -> Self { + let url_to_use = format!("{}:{}", regional_url, port); + RegionalEndpoint { url_to_use } + } +} + +impl ResolveEndpoint for RegionalEndpoint { + fn resolve_endpoint<'a>(&'a self, _params: &'a Params) -> EndpointFuture<'a> { + // Construct an endpoint using the Endpoint::Builder. Set the URL and, + // optionally, any headers to be sent with the request. For this example, + // we'll set the 'x-amz-date' header to the current date for all outgoing requests. + // `DateTime` can be used for formatting an RFC 3339 date time. + let now = SystemTime::now(); + let date_time = DateTime::from(now); + + let endpoint = Endpoint::builder() + .url(self.url_to_use.clone()) + .header( + "x-amz-date", + date_time + .fmt(DateTimeFormat::DateTimeWithOffset) + .expect("Could not create a date in UTC format"), + ) + .build(); + tracing::info!(?endpoint, "Resolving endpoint"); + EndpointFuture::ready(Ok(endpoint)) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + const DEFAULT_PORT: u16 = 13734; + + // Use the environment variable `REGIONAL_URL` for the URL. + let resolver = RegionalEndpoint::new( + std::env::var("REGIONAL_URL") + .as_deref() + .unwrap_or("http://localhost"), + DEFAULT_PORT, + ); + + let config = pokemon_service_client::Config::builder() + .endpoint_resolver(resolver) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/handling-errors.rs b/examples/legacy/pokemon-service-client-usage/examples/handling-errors.rs new file mode 100644 index 00000000000..dfcebda6109 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/handling-errors.rs @@ -0,0 +1,130 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! This example demonstrates how to handle service generated errors. +//! +//! The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +//! Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +//! file for instructions on how to launch the service locally. +//! +//! The example can be run using `cargo run --example handling-errors`. + +use pokemon_service_client::error::DisplayErrorContext; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client::{error::SdkError, operation::get_storage::GetStorageError}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // The following example sends an incorrect passcode to the operation `get_storage`, + // which will return + // [StorageAccessNotAuthorized](https://github.com/smithy-lang/smithy-rs/blob/main/codegen-core/common-test-models/pokemon.smithy#L48) + let response_result = client + .get_storage() + .user("ash") + // Give a wrong password to generate a service error. + .passcode("pkachu123") + .send() + .await; + + // All errors are consolidated into an `SdkError` + match response_result { + Ok(response) => { + tracing::info!(?response, "Response from service") + } + Err(SdkError::ServiceError(se)) => { + // When an error response is received from the service, it is modeled + // as a `SdkError::ServiceError`. + match se.err() { + // Not authorized to access Pokémon storage. + GetStorageError::StorageAccessNotAuthorized(_) => { + tracing::error!("You do not have access to this resource."); + } + GetStorageError::ResourceNotFoundError(rnfe) => { + let message = rnfe.message(); + tracing::error!(error = %message, + "Given Pikachu does not exist on the server." + ) + } + GetStorageError::ValidationError(ve) => { + tracing::error!(error = %ve, "A required field has not been set."); + } + // The SdkError is marked as `#[non_exhaustive]`. Therefore, a catch-all pattern is required to handle + // potential future variants introduced in SdkError. + _ => { + tracing::error!(error = %DisplayErrorContext(se.err()), "Some other error has occurred on the server") + } + } + } + Err(SdkError::TimeoutError(_)) => { + tracing::error!("The request timed out and could not be completed"); + } + Err(SdkError::ResponseError(re)) => { + // Raw response received from the service can be retrieved using + // the `raw()` method. + tracing::error!( + "An unparsable response was received. Raw response: {:?}", + re.raw() + ); + } + Err(sdk_error) => { + // To retrieve the `source()` of an error within the following match statements, + // we work with the parent `SdkError` type, as individual variants don't directly provide it. + // Converting the parent error to its source transfers ownership of the variable. + match sdk_error { + SdkError::DispatchFailure(ref failure) => { + if failure.is_io() { + tracing::error!("An I/O error occurred"); + } else if failure.is_timeout() { + tracing::error!("Request timed out"); + } else if failure.is_user() { + tracing::error!("An invalid HTTP request has been provided"); + } else { + tracing::error!("Some other dispatch error occurred."); + }; + + if let Ok(source) = sdk_error.into_source() { + tracing::error!(%source, "Error source"); + } + } + SdkError::ConstructionFailure(_) => { + if let Ok(source) = sdk_error.into_source() { + tracing::error!(%source, "Request could not be constructed."); + } else { + tracing::error!("Request could not be constructed for unknown reasons"); + } + } + _ => { + tracing::error!("An unknown error has occurred"); + } + } + } + } +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/mock-request.rs b/examples/legacy/pokemon-service-client-usage/examples/mock-request.rs new file mode 100644 index 00000000000..5afafdaee14 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/mock-request.rs @@ -0,0 +1,76 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to use a mock connector with `capture_request`. This allows for +/// responding with a static `Response` while capturing the incoming request. The captured request +/// can later be asserted to verify that the correct headers and body were sent to the server. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example mock-request`. +/// +use aws_smithy_runtime::client::http::test_util::capture_request; +use pokemon_service_client::primitives::SdkBody; +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Build a response that should be sent when the operation is called. + let response = http::Response::builder() + .status(200) + .body(SdkBody::from(r#"{"calls_count":100}"#)) + .expect("response could not be constructed"); + + // Call `capture_request` to obtain a HTTP connector and a request receiver. + // The request receiver captures the incoming request, while the connector can be passed + // to `Config::builder().http_client`. + let (http_client, captured_request) = capture_request(Some(response)); + + // Pass the `http_client` connector to `Config::builder`. The connector won't send + // the request over the network; instead, it will return the static response provided + // during its initialization. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + // Instantiate a client by applying the configuration. + let client = PokemonClient::from_conf(config); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .customize() + .mutate_request(|req| { + // For demonstration, send an extra header that can be verified to confirm + // that the client actually sends it. + let headers = req.headers_mut(); + headers.insert( + hyper::header::HeaderName::from_static("user-agent"), + hyper::header::HeaderName::from_static("sample-client"), + ); + }) + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); + + // The captured request can be verified to have certain headers. + let req = captured_request.expect_request(); + assert_eq!(req.headers().get("user-agent"), Some("sample-client")); + + // As an example, you can verify the URL matches. + assert_eq!(req.uri(), "http://localhost:13734/stats"); + + // You can convert the captured body into a &str and use assert! + // on it if you want to verify the contents of the request body. + // let str_body = std::str::from_utf8(req.body().bytes().unwrap()).unwrap(); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/response-header-interceptor.rs b/examples/legacy/pokemon-service-client-usage/examples/response-header-interceptor.rs new file mode 100644 index 00000000000..7f153873705 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/response-header-interceptor.rs @@ -0,0 +1,162 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +use aws_smithy_runtime_api::client::orchestrator::Metadata; +/// This example demonstrates how response headers can be examined before they are deserialized +/// into the output type. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example response-header-interceptor`. +/// +use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, BeforeTransmitInterceptorContextMut, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use uuid::Uuid; + +#[derive(Debug, Clone)] +struct RequestId { + client_id: String, + server_id: Option, +} + +impl Storable for RequestId { + type Storer = StoreReplace; +} + +#[derive(Debug, thiserror::Error)] +enum RequestIdError { + /// Client side + #[error("Client side request ID has not been set")] + ClientRequestIdMissing(), +} + +#[derive(Debug, Default)] +pub struct ResponseHeaderLoggingInterceptor; + +impl ResponseHeaderLoggingInterceptor { + /// Creates a new `ResponseHeaderLoggingInterceptor` + pub fn new() -> Self { + Self::default() + } +} + +impl Intercept for ResponseHeaderLoggingInterceptor { + fn name(&self) -> &'static str { + "ResponseHeaderLoggingInterceptor" + } + + /// Before the request is signed, add the header to the outgoing request. + fn modify_before_signing( + &self, + context: &mut BeforeTransmitInterceptorContextMut<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + let client_id = Uuid::new_v4().to_string(); + + let request_id = hyper::header::HeaderValue::from_str(&client_id) + .expect("failed to construct a header value from UUID"); + context + .request_mut() + .headers_mut() + .insert("x-amzn-requestid", request_id); + + cfg.interceptor_state().store_put(RequestId { + client_id, + server_id: None, + }); + + Ok(()) + } + + fn read_before_deserialization( + &self, + context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // `Metadata` in the `ConfigBag` has the operation name in it. + let metadata = cfg.load::().expect("metadata should exist"); + let operation_name = metadata.name().to_string(); + + // Get the server side request ID and set it in the RequestID data type + // that is in the ConfigBag. This way any other interceptor that requires the mapping + // can easily find it from the bag. + let response = context.response(); + let header_received = response + .headers() + .iter() + .find(|(header_name, _)| *header_name == "x-request-id"); + + if let Some((_, server_id)) = header_received { + let request_details = cfg + .get_mut::() + .ok_or_else(|| Box::new(RequestIdError::ClientRequestIdMissing()))?; + + tracing::info!(operation = %operation_name, + "RequestID Mapping: {} = {server_id}", + request_details.client_id, + ); + + request_details.server_id = Some(server_id.into()); + } else { + tracing::info!(operation = %operation_name, "Server RequestID missing in response"); + } + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(ResponseHeaderLoggingInterceptor) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + // If you need to access the `RequestIdError` raised by the interceptor, + // you can convert `SdkError::DispatchFailure` to a `ConnectorError` + // and then use `downcast_ref` on its source to get a `RequestIdError`. + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/retry-classifier.rs b/examples/legacy/pokemon-service-client-usage/examples/retry-classifier.rs new file mode 100644 index 00000000000..b5754a5fba1 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/retry-classifier.rs @@ -0,0 +1,112 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how a custom RetryClassifier can be written to decide +/// which error conditions should be retried. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example retry-classifier`. +/// +use http::StatusCode; +use pokemon_service_client::{ + config::{ + interceptors::InterceptorContext, + retry::{ClassifyRetry, RetryAction, RetryConfig}, + }, + operation::get_server_statistics::GetServerStatisticsError, +}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Duration; + +use pokemon_service_client::Client as PokemonClient; + +#[derive(Debug)] +struct SampleRetryClassifier; + +// By default, the generated client uses the `aws_http::retry::AwsResponseRetryClassifier` +// to determine whether an error should be retried. To use a custom retry classifier, +// implement the `ClassifyRetry` trait and pass it to the retry_classifier method +// of the `Config::builder`. +impl ClassifyRetry for SampleRetryClassifier { + fn name(&self) -> &'static str { + "SampleRetryClassifier" + } + + // For this example, the classifier should retry in case the error is GetServerStatisticsError + // and the status code is 503. + fn classify_retry(&self, ctx: &InterceptorContext) -> RetryAction { + // Get the output or error that has been deserialized from the response. + let output_or_error = ctx.output_or_error(); + + let error = match output_or_error { + Some(Ok(_)) | None => return RetryAction::NoActionIndicated, + Some(Err(err)) => err, + }; + + // Retry in case the error returned is GetServerStatisticsError and StatusCode is 503. + if let Some(_err) = error + .as_operation_error() + .and_then(|err| err.downcast_ref::()) + { + if let Some(response) = ctx.response() { + if response.status() == StatusCode::SERVICE_UNAVAILABLE.into() { + return RetryAction::server_error(); + } + } + } + + // Let other classifiers run and decide if the request should be retried. + // Returning RetryAction::RetryForbidden will forbid any retries. + RetryAction::NoActionIndicated + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default the Smithy client uses RetryConfig::standard() strategy, with 3 retries, and + // an initial exponential back off of 1 second. To turn it off use RetryConfig::disabled(). + let retry_config = RetryConfig::standard() + .with_initial_backoff(Duration::from_secs(3)) + .with_max_attempts(5); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .retry_config(retry_config) + // Add the retry classifier. + .retry_classifier(SampleRetryClassifier {}) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/retry-customize.rs b/examples/legacy/pokemon-service-client-usage/examples/retry-customize.rs new file mode 100644 index 00000000000..13c67af4655 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/retry-customize.rs @@ -0,0 +1,60 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to customize retry settings on a Smithy client. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example retry-customize`. +/// +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Duration; + +use pokemon_service_client::{config::retry::RetryConfig, Client as PokemonClient}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // By default the Smithy client uses `RetryConfig::standard()` strategy, with 3 retries, and + // an initial exponential back off of 1 second. To turn it off use `RetryConfig::disabled()`. + let retry_config = RetryConfig::standard() + .with_initial_backoff(Duration::from_secs(3)) + .with_max_attempts(5); + + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .retry_config(retry_config) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/simple-client.rs b/examples/legacy/pokemon-service-client-usage/examples/simple-client.rs new file mode 100644 index 00000000000..dbc7303386a --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/simple-client.rs @@ -0,0 +1,53 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` Client and call an +/// [operation](https://smithy.io/2.0/spec/idl.html?highlight=operation#operation-shape). +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example simple-client`. +/// +use pokemon_service_client::Client as PokemonClient; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon +/// service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client contains a type `config::Builder` for constructing a `Config` instance. + // This enables configuration of endpoint resolvers, timeouts, retries, etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + + // Instantiate a client by applying the configuration. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + // Print the response received from the service. + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/timeout-config.rs b/examples/legacy/pokemon-service-client-usage/examples/timeout-config.rs new file mode 100644 index 00000000000..717961fb96a --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/timeout-config.rs @@ -0,0 +1,64 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how to create a `smithy-rs` Client and set connection +/// and operation related timeouts on the client. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example timeout-config` +/// +use std::time::Duration; + +use pokemon_service_client::{config::timeout::TimeoutConfig, Client as PokemonClient}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // Different type of timeouts can be set on the client. These are: + // operation_attempt_timeout - If retries are enabled, this represents the timeout + // for each individual operation attempt. + // operation_timeout - Overall timeout for the operation to complete. + // connect timeout - The amount of time allowed for a connection to be established. + let timeout_config = TimeoutConfig::builder() + .operation_attempt_timeout(Duration::from_secs(1)) + .operation_timeout(Duration::from_secs(5)) + .connect_timeout(Duration::from_millis(500)) + .build(); + + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .timeout_config(timeout_config) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("Pokemon service does not seem to be running on localhost:13734"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/trace-serialize.rs b/examples/legacy/pokemon-service-client-usage/examples/trace-serialize.rs new file mode 100644 index 00000000000..c5dc8f206f1 --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/trace-serialize.rs @@ -0,0 +1,126 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +use aws_smithy_runtime::client::http::connection_poisoning::CaptureSmithyConnection; +/// This example demonstrates how an interceptor can be written to trace what is being +/// serialized / deserialized on the wire. +/// +/// Please beware that this may log sensitive information! This example is meant for pedagogical +/// purposes and may be useful in debugging scenarios. Please don't use this as-is in production. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example trace-serialize`. +/// +use http::StatusCode; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::str; + +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, BeforeTransmitInterceptorContextRef, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; + +/// An example interceptor that logs the request and response as they're sent and received. +#[derive(Debug, Default)] +pub struct WireFormatInterceptor; + +impl Intercept for WireFormatInterceptor { + fn name(&self) -> &'static str { + "WireFormatInterceptor" + } + + // Called after the operation input has been serialized but before it's dispatched over the wire. + fn read_after_serialization( + &self, + context: &BeforeTransmitInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + _cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Get the request type from the context. + let request = context.request(); + // Print the request to the debug tracing log. + tracing::debug!(?request); + + Ok(()) + } + + // Called after the operation's response has been received but before it's deserialized into the + // operation's output type. + fn read_before_deserialization( + &self, + context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + // Get the response type from the context. + let response = context.response(); + // Print the response. + if response.status().as_u16() == StatusCode::OK.as_u16() { + tracing::info!(?response, "Response received:"); + } else { + tracing::error!(?response); + } + + // Print the connection information + let captured_connection = cfg.load::().cloned(); + if let Some(captured_connection) = captured_connection.and_then(|conn| conn.get()) { + tracing::info!( + remote_addr = ?captured_connection.remote_addr(), + local_addr = ?captured_connection.local_addr(), + "Captured connection info" + ); + } else { + tracing::warn!("Connection info is missing!"); + } + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(WireFormatInterceptor {}) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("operation failed"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/examples/use-config-bag.rs b/examples/legacy/pokemon-service-client-usage/examples/use-config-bag.rs new file mode 100644 index 00000000000..9452051a6da --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/examples/use-config-bag.rs @@ -0,0 +1,140 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +/// This example demonstrates how different interceptor can use a property bag to pass +/// state from one interceptor to the next. +/// +/// The example assumes that the Pokémon service is running on the localhost on TCP port 13734. +/// Refer to the [README.md](https://github.com/smithy-lang/smithy-rs/tree/main/examples/pokemon-service-client-usage/README.md) +/// file for instructions on how to launch the service locally. +/// +/// The example can be run using `cargo run --example use-config-bag`. +/// +use aws_smithy_types::config_bag::{Storable, StoreReplace}; +use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; +use std::time::Instant; + +use pokemon_service_client::{ + config::{ + interceptors::{ + BeforeDeserializationInterceptorContextRef, FinalizerInterceptorContextRef, + }, + ConfigBag, Intercept, RuntimeComponents, + }, + error::BoxError, + Client as PokemonClient, +}; + +#[derive(Debug)] +struct RequestTimestamp(Instant); + +impl Storable for RequestTimestamp { + type Storer = StoreReplace; +} + +#[derive(Debug, Default)] +pub struct SetTimeInterceptor; + +/// Note: This is merely an example demonstrating how state can +/// be shared between two different interceptors. In a practical +/// scenario, there wouldn't be a need to write two interceptors +/// merely to display the duration from the start of the lifecycle +/// to the receipt of the response. This task can be accomplished +/// within a single interceptor by overriding both +/// read_before_execution and read_before_deserialization. +impl Intercept for SetTimeInterceptor { + fn name(&self) -> &'static str { + "SetTimeInterceptor" + } + + fn read_before_execution( + &self, + _context: &pokemon_service_client::config::interceptors::BeforeSerializationInterceptorContextRef<'_>, + cfg: &mut aws_smithy_types::config_bag::ConfigBag, + ) -> Result<(), pokemon_service_client::error::BoxError> { + cfg.interceptor_state() + .store_put(RequestTimestamp(Instant::now())); + Ok(()) + } +} + +#[derive(Debug, Default)] +pub struct GetTimeInterceptor; + +impl Intercept for GetTimeInterceptor { + fn name(&self) -> &'static str { + "GetTimeInterceptor" + } + + fn read_before_deserialization( + &self, + _context: &BeforeDeserializationInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), BoxError> { + let stop_watch = cfg + .load::() + .expect("StopWatch not found in the ConfigBag"); + + let time_taken = stop_watch.0.elapsed(); + tracing::info!(time_taken = %time_taken.as_micros(), "Microseconds:"); + + Ok(()) + } + + fn read_after_execution( + &self, + _context: &FinalizerInterceptorContextRef<'_>, + _runtime_components: &RuntimeComponents, + cfg: &mut ConfigBag, + ) -> Result<(), pokemon_service_client::error::BoxError> { + let timestamp = cfg + .load::() + .expect("RequestTimeStamp not found in the ConfigBag"); + + let time_taken = timestamp.0.elapsed(); + tracing::info!(time_taken = %time_taken.as_micros(), "Microseconds:"); + + Ok(()) + } +} + +/// Creates a new `smithy-rs` client that is configured to communicate with a locally running Pokémon service on TCP port 13734. +/// +/// # Examples +/// +/// Basic usage: +/// +/// ``` +/// let client = create_client(); +/// ``` +fn create_client() -> PokemonClient { + // The generated client has a type `Config::Builder` that can be used to build a `Config`, which + // allows configuring endpoint-resolver, timeouts, retries etc. + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .interceptor(SetTimeInterceptor) + .interceptor(GetTimeInterceptor) + .build(); + + // Apply the configuration on the client, and return that. + PokemonClient::from_conf(config) +} + +#[tokio::main] +async fn main() { + setup_tracing_subscriber(); + + // Create a configured `smithy-rs` client. + let client = create_client(); + + // Call an operation `get_server_statistics` on the Pokémon service. + let response = client + .get_server_statistics() + .send() + .await + .expect("Pokemon service does not seem to be running on localhost:13734"); + + tracing::info!(%POKEMON_SERVICE_URL, ?response, "Response received"); +} diff --git a/examples/legacy/pokemon-service-client-usage/src/lib.rs b/examples/legacy/pokemon-service-client-usage/src/lib.rs new file mode 100644 index 00000000000..6612ddb4c4c --- /dev/null +++ b/examples/legacy/pokemon-service-client-usage/src/lib.rs @@ -0,0 +1,19 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ +pub static POKEMON_SERVICE_URL: &str = "http://localhost:13734"; + +/// Sets up the tracing subscriber to print `tracing::info!` and `tracing::error!` messages on the console. +pub fn setup_tracing_subscriber() { + // Add a tracing subscriber that uses the environment variable RUST_LOG + // to figure out which log level should be emitted. By default use `tracing::info!` + // as the logging level. + let filter = tracing_subscriber::EnvFilter::builder() + .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into()) + .from_env_lossy(); + + tracing_subscriber::fmt::fmt() + .with_env_filter(filter) + .init(); +} diff --git a/examples/legacy/pokemon-service-common/Cargo.toml b/examples/legacy/pokemon-service-common/Cargo.toml new file mode 100644 index 00000000000..de77646d3d0 --- /dev/null +++ b/examples/legacy/pokemon-service-common/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "pokemon-service-common" +version = "0.1.0" +edition = "2021" +publish = false +authors = ["Smithy-rs Server Team "] +description = "A smithy Rust service to retrieve information about Pokémon." + +[dependencies] +async-stream = "0.3" +http = "0.2.9" +rand = "0.8" +tracing = "0.1" +tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"] } +tokio = { version = "1", default-features = false, features = ["time"] } +tower = "0.4" + +# Local paths +aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client", "connector-hyper-0-14-x", "tls-rustls"] } +aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } +pokemon-service-client = { path = "../pokemon-service-client/", package = "pokemon-service-client-http0x", features = [ + "behavior-version-latest", +] } +pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk", package = "pokemon-service-server-sdk-http0x" } + +[dev-dependencies] +aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["test-util"] } diff --git a/examples/legacy/pokemon-service-common/src/lib.rs b/examples/legacy/pokemon-service-common/src/lib.rs new file mode 100644 index 00000000000..9fc8c004577 --- /dev/null +++ b/examples/legacy/pokemon-service-common/src/lib.rs @@ -0,0 +1,378 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Pokémon Service +//! +//! This crate implements the Pokémon Service. +#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)] +use std::{ + collections::HashMap, + convert::TryInto, + process::Child, + sync::{atomic::AtomicUsize, Arc}, +}; + +use async_stream::stream; +use aws_smithy_runtime::client::http::hyper_014::HyperConnector; +use aws_smithy_runtime_api::client::http::HttpConnector; +use http::Uri; +use pokemon_service_server_sdk::{ + error, input, model, + model::CapturingPayload, + output, + server::Extension, + types::{Blob, ByteStream, SdkBody}, +}; +use rand::{seq::SliceRandom, Rng}; +use tracing_subscriber::{prelude::*, EnvFilter}; + +const PIKACHU_ENGLISH_FLAVOR_TEXT: &str = + "When several of these Pokémon gather, their electricity could build and cause lightning storms."; +const PIKACHU_SPANISH_FLAVOR_TEXT: &str = + "Cuando varios de estos Pokémon se juntan, su energía puede causar fuertes tormentas."; +const PIKACHU_ITALIAN_FLAVOR_TEXT: &str = + "Quando vari Pokémon di questo tipo si radunano, la loro energia può causare forti tempeste."; +const PIKACHU_JAPANESE_FLAVOR_TEXT: &str = + "ほっぺたの りょうがわに ちいさい でんきぶくろを もつ。ピンチのときに ほうでんする。"; + +/// Kills [`Child`] process when dropped. +#[derive(Debug)] +#[must_use] +pub struct ChildDrop(pub Child); + +impl Drop for ChildDrop { + fn drop(&mut self) { + self.0.kill().expect("failed to kill process") + } +} + +/// Setup `tracing::subscriber` to read the log level from RUST_LOG environment variable. +pub fn setup_tracing() { + let format = tracing_subscriber::fmt::layer().json(); + let filter = EnvFilter::try_from_default_env() + .or_else(|_| EnvFilter::try_new("info")) + .unwrap(); + tracing_subscriber::registry() + .with(format) + .with(filter) + .init(); +} + +/// Structure holding the translations for a Pokémon description. +#[derive(Debug)] +struct PokemonTranslations { + en: String, + es: String, + it: String, + jp: String, +} + +/// PokémonService shared state. +/// +/// Some applications may want to manage state between handlers. Imagine having a database connection pool +/// that can be shared between different handlers and operation implementations. +/// State management can be expressed in a struct where the attributes hold the shared entities. +/// +/// **NOTE: It is up to the implementation of the state structure to handle concurrency by protecting** +/// **its attributes using synchronization mechanisms.** +/// +/// The framework stores the `Arc` inside an `http::Extensions` and conveniently passes it to +/// the operation's implementation, making it able to handle operations with two different async signatures: +/// * `FnOnce(InputType) -> Future` +/// * `FnOnce(InputType, Extension>) -> Future` +/// +/// Wrapping the service with a [`tower::Layer`] will allow to have operations' signatures with and without shared state: +/// +/// ```compile_fail +/// use std::sync::Arc; +/// use aws_smithy_http_server::{AddExtensionLayer, Extension, Router}; +/// use tower::ServiceBuilder; +/// use tokio::sync::RwLock; +/// +/// // Shared state, +/// #[derive(Debug, State)] +/// pub struct State { +/// pub count: RwLock +/// } +/// +/// // Operation implementation with shared state. +/// async fn operation_with_state(input: Input, state: Extension>) -> Output { +/// let mut count = state.0.write().await; +/// *count += 1; +/// Ok(Output::new()) +/// } +/// +/// // Operation implementation without shared state. +/// async fn operation_without_state(input: Input) -> Output { +/// Ok(Output::new()) +/// } +/// +/// let app: Router = OperationRegistryBuilder::default() +/// .operation_with_state(operation_with_state) +/// .operation_without_state(operation_without_state) +/// .build() +/// .unwrap() +/// .into(); +/// let shared_state = Arc::new(State::default()); +/// let app = app.layer(ServiceBuilder::new().layer(AddExtensionLayer::new(shared_state))); +/// let server = hyper::Server::bind(&"0.0.0.0:13734".parse().unwrap()).serve(app.into_make_service()); +/// ... +/// ``` +/// +/// Without the middleware layer, the framework will require operations' signatures without +/// the shared state. +/// +/// [`middleware`]: [`aws_smithy_http_server::AddExtensionLayer`] +#[derive(Debug)] +pub struct State { + pokemons_translations: HashMap, + call_count: AtomicUsize, +} + +impl Default for State { + fn default() -> Self { + let mut pokemons_translations = HashMap::new(); + pokemons_translations.insert( + String::from("pikachu"), + PokemonTranslations { + en: String::from(PIKACHU_ENGLISH_FLAVOR_TEXT), + es: String::from(PIKACHU_SPANISH_FLAVOR_TEXT), + it: String::from(PIKACHU_ITALIAN_FLAVOR_TEXT), + jp: String::from(PIKACHU_JAPANESE_FLAVOR_TEXT), + }, + ); + Self { + pokemons_translations, + call_count: Default::default(), + } + } +} + +/// Retrieves information about a Pokémon species. +pub async fn get_pokemon_species( + input: input::GetPokemonSpeciesInput, + state: Extension>, +) -> Result { + state + .0 + .call_count + .fetch_add(1, std::sync::atomic::Ordering::SeqCst); + // We only support retrieving information about Pikachu. + let pokemon = state.0.pokemons_translations.get(&input.name); + match pokemon.as_ref() { + Some(pokemon) => { + tracing::debug!("Requested Pokémon is {}", input.name); + let flavor_text_entries = vec![ + model::FlavorText { + flavor_text: pokemon.en.to_owned(), + language: model::Language::English, + }, + model::FlavorText { + flavor_text: pokemon.es.to_owned(), + language: model::Language::Spanish, + }, + model::FlavorText { + flavor_text: pokemon.it.to_owned(), + language: model::Language::Italian, + }, + model::FlavorText { + flavor_text: pokemon.jp.to_owned(), + language: model::Language::Japanese, + }, + ]; + let output = output::GetPokemonSpeciesOutput { + name: String::from("pikachu"), + flavor_text_entries, + }; + Ok(output) + } + None => { + tracing::error!("Requested Pokémon {} not available", input.name); + Err(error::GetPokemonSpeciesError::ResourceNotFoundException( + error::ResourceNotFoundException { + message: String::from("Requested Pokémon not available"), + }, + )) + } + } +} + +/// Retrieves the user's storage. +pub async fn get_storage( + input: input::GetStorageInput, + _state: Extension>, +) -> Result { + tracing::debug!("attempting to authenticate storage user"); + + // We currently only support Ash and he has nothing stored + if !(input.user == "ash" && input.passcode == "pikachu123") { + tracing::debug!("authentication failed"); + return Err(error::GetStorageError::StorageAccessNotAuthorized( + error::StorageAccessNotAuthorized {}, + )); + } + Ok(output::GetStorageOutput { collection: vec![] }) +} + +/// Calculates and reports metrics about this server instance. +pub async fn get_server_statistics( + _input: input::GetServerStatisticsInput, + state: Extension>, +) -> output::GetServerStatisticsOutput { + // Read the current calls count. + let counter = state.0.call_count.load(std::sync::atomic::Ordering::SeqCst); + let calls_count = counter + .try_into() + .map_err(|e| { + tracing::error!("Unable to convert u64 to i64: {}", e); + }) + .unwrap_or(0); + tracing::debug!("This instance served {} requests", counter); + output::GetServerStatisticsOutput { calls_count } +} + +/// Attempts to capture a Pokémon. +pub async fn capture_pokemon( + mut input: input::CapturePokemonInput, +) -> Result { + if input.region != "Kanto" { + return Err(error::CapturePokemonError::UnsupportedRegionError( + error::UnsupportedRegionError { + region: input.region, + }, + )); + } + let output_stream = stream! { + loop { + use std::time::Duration; + match input.events.recv().await { + Ok(maybe_event) => match maybe_event { + Some(event) => { + let capturing_event = event.as_event(); + if let Ok(attempt) = capturing_event { + let payload = attempt.payload.clone().unwrap_or_else(|| CapturingPayload::builder().build()); + let pokeball = payload.pokeball().unwrap_or(""); + if ! matches!(pokeball, "Master Ball" | "Great Ball" | "Fast Ball") { + yield Err( + crate::error::CapturePokemonEventsError::InvalidPokeballError( + crate::error::InvalidPokeballError { + pokeball: pokeball.to_owned() + } + ) + ); + } else { + let captured = match pokeball { + "Master Ball" => true, + "Great Ball" => rand::thread_rng().gen_range(0..100) > 33, + "Fast Ball" => rand::thread_rng().gen_range(0..100) > 66, + _ => unreachable!("invalid pokeball"), + }; + // Only support Kanto + tokio::time::sleep(Duration::from_millis(1000)).await; + // Will it capture the Pokémon? + if captured { + let shiny = rand::thread_rng().gen_range(0..4096) == 0; + let pokemon = payload + .name() + .unwrap_or("") + .to_string(); + let pokedex: Vec = (0..255).collect(); + yield Ok(crate::model::CapturePokemonEvents::Event( + crate::model::CaptureEvent { + name: Some(pokemon), + shiny: Some(shiny), + pokedex_update: Some(Blob::new(pokedex)), + captured: Some(true), + } + )); + } + } + } + } + None => break, + }, + Err(e) => println!("{e:?}"), + } + } + }; + Ok(output::CapturePokemonOutput::builder() + .events(output_stream.into()) + .build() + .unwrap()) +} + +/// Empty operation used to benchmark the service. +pub async fn do_nothing(_input: input::DoNothingInput) -> output::DoNothingOutput { + output::DoNothingOutput {} +} + +/// Operation used to show the service is running. +pub async fn check_health(_input: input::CheckHealthInput) -> output::CheckHealthOutput { + output::CheckHealthOutput {} +} + +const RADIO_STREAMS: [&str; 2] = [ + "https://ia800107.us.archive.org/33/items/299SoundEffectCollection/102%20Palette%20Town%20Theme.mp3", + "https://ia600408.us.archive.org/29/items/PocketMonstersGreenBetaLavenderTownMusicwwwFlvtoCom/Pocket%20Monsters%20Green%20Beta-%20Lavender%20Town%20Music-%5Bwww_flvto_com%5D.mp3", +]; + +/// Streams a random Pokémon song. +pub async fn stream_pokemon_radio( + _input: input::StreamPokemonRadioInput, +) -> output::StreamPokemonRadioOutput { + let radio_stream_url = RADIO_STREAMS + .choose(&mut rand::thread_rng()) + .expect("`RADIO_STREAMS` is empty") + .parse::() + .expect("Invalid url in `RADIO_STREAMS`"); + + let connector = HyperConnector::builder().build_https(); + let result = connector + .call( + http::Request::builder() + .uri(radio_stream_url) + .body(SdkBody::empty()) + .unwrap() + .try_into() + .unwrap(), + ) + .await + .unwrap(); + + output::StreamPokemonRadioOutput { + data: ByteStream::new(result.into_body()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn get_pokemon_species_pikachu_spanish_flavor_text() { + let input = input::GetPokemonSpeciesInput { + name: String::from("pikachu"), + }; + + let state = Arc::new(State::default()); + + let actual_spanish_flavor_text = get_pokemon_species(input, Extension(state.clone())) + .await + .unwrap() + .flavor_text_entries + .into_iter() + .find(|flavor_text| flavor_text.language == model::Language::Spanish) + .unwrap(); + + assert_eq!( + PIKACHU_SPANISH_FLAVOR_TEXT, + actual_spanish_flavor_text.flavor_text() + ); + + let input = input::GetServerStatisticsInput {}; + let stats = get_server_statistics(input, Extension(state.clone())).await; + assert_eq!(1, stats.calls_count); + } +} diff --git a/examples/legacy/pokemon-service-common/tests/plugins_execution_order.rs b/examples/legacy/pokemon-service-common/tests/plugins_execution_order.rs new file mode 100644 index 00000000000..ee0fbad3526 --- /dev/null +++ b/examples/legacy/pokemon-service-common/tests/plugins_execution_order.rs @@ -0,0 +1,121 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::{ + ops::Deref, + sync::Arc, + sync::Mutex, + task::{Context, Poll}, +}; + +use pokemon_service_server_sdk::{ + server::plugin::{HttpMarker, HttpPlugins, Plugin}, + PokemonService, PokemonServiceConfig, +}; +use tower::{Layer, Service}; + +use aws_smithy_runtime::client::http::test_util::capture_request; +use pokemon_service_client::{Client, Config}; +use pokemon_service_common::do_nothing; + +#[tokio::test] +async fn plugin_layers_are_executed_in_registration_order() { + // Each plugin layer will push its name into this vector when it gets invoked. + // We can then check the vector content to verify the invocation order + let output = Arc::new(Mutex::new(Vec::new())); + + let http_plugins = HttpPlugins::new() + .push(SentinelPlugin::new("first", output.clone())) + .push(SentinelPlugin::new("second", output.clone())); + let config = PokemonServiceConfig::builder() + .http_plugin(http_plugins) + .build(); + let mut app = PokemonService::builder(config) + .do_nothing(do_nothing) + .build_unchecked(); + + let request = { + let (http_client, rcvr) = capture_request(None); + let config = Config::builder() + .http_client(http_client) + .endpoint_url("http://localhost:1234") + .build(); + Client::from_conf(config).do_nothing().send().await.unwrap(); + rcvr.expect_request() + }; + + app.call(request.try_into().unwrap()).await.unwrap(); + + let output_guard = output.lock().unwrap(); + assert_eq!(output_guard.deref(), &vec!["first", "second"]); +} + +struct SentinelPlugin { + name: &'static str, + output: Arc>>, +} + +impl SentinelPlugin { + pub fn new(name: &'static str, output: Arc>>) -> Self { + Self { name, output } + } +} + +impl Plugin for SentinelPlugin { + type Output = SentinelService; + + fn apply(&self, inner: T) -> Self::Output { + SentinelService { + inner, + name: self.name, + output: self.output.clone(), + } + } +} + +impl HttpMarker for SentinelPlugin {} + +#[derive(Clone, Debug)] +pub struct SentinelService { + inner: S, + output: Arc>>, + name: &'static str, +} + +impl Service for SentinelService +where + S: Service, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, req: R) -> Self::Future { + self.output.lock().unwrap().push(self.name); + self.inner.call(req) + } +} + +#[derive(Debug)] +pub struct SentinelLayer { + name: &'static str, + output: Arc>>, +} + +impl Layer for SentinelLayer { + type Service = SentinelService; + + fn layer(&self, service: S) -> Self::Service { + SentinelService { + inner: service, + output: self.output.clone(), + name: self.name, + } + } +} diff --git a/examples/legacy/pokemon-service-lambda/Cargo.toml b/examples/legacy/pokemon-service-lambda/Cargo.toml new file mode 100644 index 00000000000..5046d855438 --- /dev/null +++ b/examples/legacy/pokemon-service-lambda/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "pokemon-service-lambda" +version = "0.1.0" +edition = "2021" +publish = false +authors = ["Smithy-rs Server Team "] +description = "A smithy Rust service to retrieve information about Pokémon via Lambda." + +[dependencies] +async-stream = "0.3.4" +clap = { version = "4.1.11", features = ["derive"] } +hyper = {version = "0.14.26", features = ["server"] } +tokio = "1.26.0" +tracing = "0.1" + +# `aws-smithy-legacy-http-server` is only guaranteed to be compatible with this +# version of `lambda_http`, or semver-compatible versions of this version. +# Depending on other versions of `lambda_http` may not work. +lambda_http = "0.8.0" + +# Local paths +pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/", package = "pokemon-service-server-sdk-http0x", features = ["aws-lambda"] } +pokemon-service-common = { path = "../pokemon-service-common/" } diff --git a/examples/legacy/pokemon-service-lambda/src/lib.rs b/examples/legacy/pokemon-service-lambda/src/lib.rs new file mode 100644 index 00000000000..81f7c97cb20 --- /dev/null +++ b/examples/legacy/pokemon-service-lambda/src/lib.rs @@ -0,0 +1,32 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::sync::Arc; + +use pokemon_service_common::State; +use pokemon_service_server_sdk::{ + error::{GetStorageError, StorageAccessNotAuthorized}, + input::GetStorageInput, + output::GetStorageOutput, + server::{request::lambda::Context, Extension}, +}; + +/// Retrieves the user's storage and logs the lambda request ID. +pub async fn get_storage_lambda( + input: GetStorageInput, + _state: Extension>, + context: Context, +) -> Result { + tracing::debug!(request_id = %context.request_id, "attempting to authenticate storage user"); + + // We currently only support Ash and he has nothing stored + if !(input.user == "ash" && input.passcode == "pikachu123") { + tracing::debug!("authentication failed"); + return Err(GetStorageError::StorageAccessNotAuthorized( + StorageAccessNotAuthorized {}, + )); + } + Ok(GetStorageOutput { collection: vec![] }) +} diff --git a/examples/legacy/pokemon-service-lambda/src/main.rs b/examples/legacy/pokemon-service-lambda/src/main.rs new file mode 100644 index 00000000000..93de83b2ede --- /dev/null +++ b/examples/legacy/pokemon-service-lambda/src/main.rs @@ -0,0 +1,46 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::sync::Arc; + +use pokemon_service_common::{ + capture_pokemon, check_health, do_nothing, get_pokemon_species, get_server_statistics, + setup_tracing, stream_pokemon_radio, State, +}; +use pokemon_service_lambda::get_storage_lambda; +use pokemon_service_server_sdk::{ + server::{routing::LambdaHandler, AddExtensionLayer}, + PokemonService, PokemonServiceConfig, +}; + +#[tokio::main] +pub async fn main() { + setup_tracing(); + + let config = PokemonServiceConfig::builder() + // Set up shared state and middlewares. + .layer(AddExtensionLayer::new(Arc::new(State::default()))) + .build(); + let app = PokemonService::builder(config) + // Build a registry containing implementations to all the operations in the service. These + // are async functions or async closures that take as input the operation's input and + // return the operation's output. + .get_pokemon_species(get_pokemon_species) + .get_storage(get_storage_lambda) + .get_server_statistics(get_server_statistics) + .capture_pokemon(capture_pokemon) + .do_nothing(do_nothing) + .check_health(check_health) + .stream_pokemon_radio(stream_pokemon_radio) + .build() + .expect("failed to build an instance of PokemonService"); + + let handler = LambdaHandler::new(app); + let lambda = lambda_http::run(handler); + + if let Err(err) = lambda.await { + eprintln!("lambda error: {err}"); + } +} diff --git a/examples/legacy/pokemon-service-lambda/tests/fixtures/example-apigw-request.json b/examples/legacy/pokemon-service-lambda/tests/fixtures/example-apigw-request.json new file mode 100644 index 00000000000..9ba7dcf8bd1 --- /dev/null +++ b/examples/legacy/pokemon-service-lambda/tests/fixtures/example-apigw-request.json @@ -0,0 +1,89 @@ +{ + "body": null, + "headers": { + "Accept": "application/json", + "Accept-Encoding": "gzip, deflate", + "cache-control": "no-cache", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Content-Type": "application/json", + "headerName": "headerValue", + "Host": "gy415nuibc.execute-api.us-east-1.amazonaws.com", + "Postman-Token": "9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f", + "User-Agent": "PostmanRuntime/2.4.5", + "Via": "1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A==", + "X-Forwarded-For": "54.240.196.186, 54.182.214.83", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "httpMethod": "GET", + "isBase64Encoded": false, + "multiValueHeaders": { + "Accept": ["application/json"], + "Accept-Encoding": ["gzip, deflate"], + "cache-control": ["no-cache"], + "CloudFront-Forwarded-Proto": ["https"], + "CloudFront-Is-Desktop-Viewer": ["true"], + "CloudFront-Is-Mobile-Viewer": ["false"], + "CloudFront-Is-SmartTV-Viewer": ["false"], + "CloudFront-Is-Tablet-Viewer": ["false"], + "CloudFront-Viewer-Country": ["US"], + "Content-Type": ["application/json"], + "headerName": ["headerValue"], + "Host": ["gy415nuibc.execute-api.us-east-1.amazonaws.com"], + "Postman-Token": ["9f583ef0-ed83-4a38-aef3-eb9ce3f7a57f"], + "User-Agent": ["PostmanRuntime/2.4.5"], + "Via": ["1.1 d98420743a69852491bbdea73f7680bd.cloudfront.net (CloudFront)"], + "X-Amz-Cf-Id": ["pn-PWIJc6thYnZm5P0NMgOUglL1DYtl0gdeJky8tqsg8iS_sgsKD1A=="], + "X-Forwarded-For": ["54.240.196.186, 54.182.214.83"], + "X-Forwarded-Port": ["443"], + "X-Forwarded-Proto": ["https"] + }, + "multiValueQueryStringParameters": { + "key": ["value"] + }, + "path": "/stats", + "pathParameters": null, + "queryStringParameters": { + "key": "value" + }, + "requestContext": { + "accountId": "xxxxx", + "apiId": "xxxxx", + "domainName": "testPrefix.testDomainName", + "domainPrefix": "testPrefix", + "extendedRequestId": "NvWWKEZbliAFliA=", + "httpMethod": "GET", + "identity": { + "accessKey": "xxxxx", + "accountId": "xxxxx", + "apiKey": "test-invoke-api-key", + "apiKeyId": "test-invoke-api-key-id", + "caller": "xxxxx:xxxxx", + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "test-invoke-source-ip", + "user": "xxxxx:xxxxx", + "userAgent": "aws-internal/3 aws-sdk-java/1.12.154 Linux/5.4.156-94.273.amzn2int.x86_64 OpenJDK_64-Bit_Server_VM/25.322-b06 java/1.8.0_322 vendor/Oracle_Corporation cfg/retry-mode/standard", + "userArn": "arn:aws:sts::xxxxx:assumed-role/xxxxx/xxxxx" + }, + "path": "/stats", + "protocol": "HTTP/1.1", + "requestId": "e5488776-afe4-4e5e-92b1-37bd23f234d6", + "requestTime": "18/Feb/2022:13:23:12 +0000", + "requestTimeEpoch": 1645190592806, + "resourceId": "ddw8yd", + "resourcePath": "/stats", + "stage": "test-invoke-stage" + }, + "resource": "/stats", + "stageVariables": null +} diff --git a/examples/legacy/pokemon-service-tls/Cargo.toml b/examples/legacy/pokemon-service-tls/Cargo.toml new file mode 100644 index 00000000000..0c3e5648699 --- /dev/null +++ b/examples/legacy/pokemon-service-tls/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "pokemon-service-tls" +version = "0.1.0" +edition = "2021" +publish = false +authors = ["Smithy-rs Server Team "] +description = "A smithy Rust service to retrieve information about Pokémon." + +[dependencies] +clap = { version = "4.1.11", features = ["derive"] } +hyper = { version = "0.14.26", features = ["server"] } +tokio = "1.26.0" +tracing = "0.1" + +# These dependencies are only required for the `pokemon-service-tls` program. + +# Latest version supporting hyper 0.x +tls-listener = { version = "0.8", features = ["rustls", "hyper-h2"] } +tokio-rustls = "0.24" +rustls-pemfile = "1" +futures-util = { version = "0.3.29", default-features = false } + +# Local paths +pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/", package = "pokemon-service-server-sdk-http0x" } +pokemon-service-common = { path = "../pokemon-service-common/" } + +[dev-dependencies] +assert_cmd = "2.0" +serial_test = "3.1.1" + +# These dependencies are only required for testing the `pokemon-service-tls` program. +hyper-rustls = { version = "0.24", features = ["http2"] } +hyper-tls = { version = "0.5" } + +# Local paths +aws-smithy-legacy-http = { path = "../../../rust-runtime/aws-smithy-legacy-http/" } +aws-smithy-runtime = { path = "../../../rust-runtime/aws-smithy-runtime", features = ["client", "connector-hyper-0-14-x"] } +aws-smithy-types = { path = "../../../rust-runtime/aws-smithy-types/" } +pokemon-service-client = { path = "../pokemon-service-client/", package = "pokemon-service-client-http0x", features = [ + "behavior-version-latest", +] } diff --git a/examples/legacy/pokemon-service-tls/src/lib.rs b/examples/legacy/pokemon-service-tls/src/lib.rs new file mode 100644 index 00000000000..d5006504e1d --- /dev/null +++ b/examples/legacy/pokemon-service-tls/src/lib.rs @@ -0,0 +1,13 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +// Defaults shared between `main.rs` and `/tests`. +pub const DEFAULT_TEST_KEY: &str = + concat!(env!("CARGO_MANIFEST_DIR"), "/tests/testdata/localhost.key"); +pub const DEFAULT_TEST_CERT: &str = + concat!(env!("CARGO_MANIFEST_DIR"), "/tests/testdata/localhost.crt"); +pub const DEFAULT_ADDRESS: &str = "127.0.0.1"; +pub const DEFAULT_PORT: u16 = 13734; +pub const DEFAULT_DOMAIN: &str = "localhost"; diff --git a/examples/legacy/pokemon-service-tls/src/main.rs b/examples/legacy/pokemon-service-tls/src/main.rs new file mode 100644 index 00000000000..b077c5ca37f --- /dev/null +++ b/examples/legacy/pokemon-service-tls/src/main.rs @@ -0,0 +1,191 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +// This program is exported as a binary named `pokemon-service-tls`. +// It uses `tls-listener`, `tokio-rustls` (and `rustls-pemfile` to parse PEM files) +// to serve TLS connections. It also enables h2 ALPN protocol, +// without this clients by default don't upgrade to http2. +// +// You can use `mkcert` (https://github.com/FiloSottile/mkcert) to create certificates for testing: +// `$ mkcert localhost` +// it should create `./localhost.pem` and `./localhost-key.pem`, +// then you can run TLS server via: +// `$ cargo run --bin pokemon-service-tls -- --tls-cert-path ./localhost.pem --tls-key-path ./localhost-key.pem` +// and test it: +// ```bash +// $ curl -k -D- -H "Accept: application/json" https://localhost:13734/pokemon-species/pikachu +// HTTP/2 200 +// # ... +// ``` +// note that by default created certificates will be unknown and you should use `-k|--insecure` +// flag while making requests with cURL or you can run `mkcert -install` to trust certificates created by `mkcert`. + +use std::{fs::File, future, io::BufReader, net::SocketAddr, sync::Arc}; + +use clap::Parser; +use futures_util::stream::StreamExt; +use tokio_rustls::{ + rustls::{Certificate, PrivateKey, ServerConfig}, + TlsAcceptor, +}; + +use pokemon_service_common::{ + capture_pokemon, check_health, get_pokemon_species, get_server_statistics, get_storage, + setup_tracing, stream_pokemon_radio, State, +}; +use pokemon_service_server_sdk::{ + input, output, + server::{request::connect_info::ConnectInfo, routing::Connected, AddExtensionLayer}, + PokemonService, PokemonServiceConfig, +}; +use pokemon_service_tls::{DEFAULT_ADDRESS, DEFAULT_PORT, DEFAULT_TEST_CERT, DEFAULT_TEST_KEY}; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Hyper server bind address. + #[clap(short, long, action, default_value = DEFAULT_ADDRESS)] + address: String, + /// Hyper server bind port. + #[clap(short, long, action, default_value_t = DEFAULT_PORT)] + port: u16, + /// Hyper server TLS certificate path. Must be a PEM file. + #[clap(long, default_value = DEFAULT_TEST_CERT)] + tls_cert_path: String, + /// Hyper server TLS private key path. Must be a PEM file. + #[clap(long, default_value = DEFAULT_TEST_KEY)] + tls_key_path: String, +} + +/// Information derived from the TLS connection. +#[derive(Debug, Clone)] +pub struct TlsConnectInfo { + /// The remote peer address of this connection. + pub socket_addr: SocketAddr, + + /// The set of TLS certificates presented by the peer in this connection. + pub certs: Option>>, +} + +impl Connected<&tokio_rustls::server::TlsStream> + for TlsConnectInfo +{ + fn connect_info( + target: &tokio_rustls::server::TlsStream, + ) -> Self { + let (addr_stream, session) = target.get_ref(); + let socket_addr = addr_stream.remote_addr(); + + let certs = session + .peer_certificates() + .map(|certs| Arc::new(certs.to_vec())); + + TlsConnectInfo { socket_addr, certs } + } +} + +/// Empty operation used to showcase how we can get access to information derived from the TLS +/// connection in. +pub async fn do_nothing_with_tls_connect_info( + _input: input::DoNothingInput, + ConnectInfo(tls_connect_info): ConnectInfo, +) -> output::DoNothingOutput { + // Logging these might pose a security concern! You probably don't want to do this in + // production. + tracing::debug!(?tls_connect_info.certs, "peer TLS certificates"); + + output::DoNothingOutput {} +} + +#[tokio::main] +pub async fn main() { + let args = Args::parse(); + setup_tracing(); + + let config = PokemonServiceConfig::builder() + // Set up shared state and middlewares. + .layer(AddExtensionLayer::new(Arc::new(State::default()))) + .build(); + let app = PokemonService::builder(config) + // Build a registry containing implementations to all the operations in the service. These + // are async functions or async closures that take as input the operation's input and + // return the operation's output. + .get_pokemon_species(get_pokemon_species) + .get_storage(get_storage) + .get_server_statistics(get_server_statistics) + .capture_pokemon(capture_pokemon) + .do_nothing(do_nothing_with_tls_connect_info) + .check_health(check_health) + .stream_pokemon_radio(stream_pokemon_radio) + .build() + .expect("failed to build an instance of PokemonService"); + + let addr: SocketAddr = format!("{}:{}", args.address, args.port) + .parse() + .expect("unable to parse the server bind address and port"); + + let acceptor = acceptor(&args.tls_cert_path, &args.tls_key_path); + let listener = tls_listener::TlsListener::new( + acceptor, + hyper::server::conn::AddrIncoming::bind(&addr).expect("could not bind"), + ) + .connections() + .filter(|conn| { + if let Err(err) = conn { + eprintln!("connection error: {err:?}"); + future::ready(false) + } else { + future::ready(true) + } + }); + // Using `into_make_service_with_connect_info`, rather than `into_make_service`, to adjoin the `TlsConnectInfo` + // connection info. + let make_app = app.into_make_service_with_connect_info::(); + let server = + hyper::Server::builder(hyper::server::accept::from_stream(listener)).serve(make_app); + if let Err(err) = server.await { + eprintln!("server error: {err}"); + } +} + +// Returns a `TlsAcceptor` that can be used to create `TlsListener` +// which then can be used with Hyper. +pub fn acceptor(cert_path: &str, key_path: &str) -> TlsAcceptor { + let certs = load_certs(cert_path); + let key = load_key(key_path); + let mut server_config = ServerConfig::builder() + .with_safe_defaults() + .with_no_client_auth() + .with_single_cert(certs, key) + .expect("could not create server config"); + + // If we don't state we are accepting "h2", clients by default don't negotiate way up to http2. + server_config.alpn_protocols = vec!["h2".into(), "http/1.1".into()]; + + TlsAcceptor::from(Arc::new(server_config)) +} + +fn load_certs(path: &str) -> Vec { + let mut reader = BufReader::new(File::open(path).expect("could not open certificate")); + rustls_pemfile::certs(&mut reader) + .expect("could not parse certificate") + .into_iter() + .map(Certificate) + .collect() +} + +fn load_key(path: &str) -> PrivateKey { + let mut reader = BufReader::new(File::open(path).expect("could not open private key")); + loop { + match rustls_pemfile::read_one(&mut reader).expect("could not parse private key") { + Some(rustls_pemfile::Item::RSAKey(key)) => return PrivateKey(key), + Some(rustls_pemfile::Item::PKCS8Key(key)) => return PrivateKey(key), + Some(rustls_pemfile::Item::ECKey(key)) => return PrivateKey(key), + None => break, + _ => {} + } + } + panic!("invalid private key") +} diff --git a/examples/legacy/pokemon-service-tls/tests/common/mod.rs b/examples/legacy/pokemon-service-tls/tests/common/mod.rs new file mode 100644 index 00000000000..8954365a205 --- /dev/null +++ b/examples/legacy/pokemon-service-tls/tests/common/mod.rs @@ -0,0 +1,81 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::{fs::File, io::BufReader, process::Command, time::Duration}; + +use assert_cmd::prelude::*; +use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; +use tokio::time::sleep; + +use pokemon_service_client::{Client, Config}; +use pokemon_service_common::ChildDrop; +use pokemon_service_tls::{DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_TEST_CERT}; + +pub async fn run_server() -> ChildDrop { + let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); + let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); + + sleep(Duration::from_millis(500)).await; + + ChildDrop(child) +} + +// Returns a client that only talks through https and http2 connections. +// It is useful in testing whether our server can talk to http2. +pub fn client_http2_only() -> Client { + // Create custom cert store and add our test certificate to prevent unknown cert issues. + let mut reader = + BufReader::new(File::open(DEFAULT_TEST_CERT).expect("could not open certificate")); + let certs = rustls_pemfile::certs(&mut reader).expect("could not parse certificate"); + let mut roots = tokio_rustls::rustls::RootCertStore::empty(); + roots.add_parsable_certificates(&certs); + + let connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config( + tokio_rustls::rustls::ClientConfig::builder() + .with_safe_defaults() + .with_root_certificates(roots) + .with_no_client_auth(), + ) + .https_only() + .enable_http2() + .build(); + + let config = Config::builder() + .http_client(HyperClientBuilder::new().build(connector)) + .endpoint_url(format!("https://{DEFAULT_DOMAIN}:{DEFAULT_PORT}")) + .build(); + Client::from_conf(config) +} + +/// A `hyper` connector that uses the `native-tls` crate for TLS. To use this in a Smithy client, +/// wrap with a [`HyperClientBuilder`]. +pub type NativeTlsConnector = hyper_tls::HttpsConnector; + +fn native_tls_connector() -> NativeTlsConnector { + let cert = hyper_tls::native_tls::Certificate::from_pem( + std::fs::read_to_string(DEFAULT_TEST_CERT) + .expect("could not open certificate") + .as_bytes(), + ) + .expect("could not parse certificate"); + + let tls_connector = hyper_tls::native_tls::TlsConnector::builder() + .min_protocol_version(Some(hyper_tls::native_tls::Protocol::Tlsv12)) + .add_root_certificate(cert) + .build() + .unwrap_or_else(|e| panic!("error while creating TLS connector: {}", e)); + let mut http_connector = hyper::client::HttpConnector::new(); + http_connector.enforce_http(false); + hyper_tls::HttpsConnector::from((http_connector, tls_connector.into())) +} + +pub fn native_tls_client() -> Client { + let config = Config::builder() + .http_client(HyperClientBuilder::new().build(native_tls_connector())) + .endpoint_url(format!("https://{DEFAULT_DOMAIN}:{DEFAULT_PORT}")) + .build(); + Client::from_conf(config) +} diff --git a/examples/legacy/pokemon-service-tls/tests/custom_connectors.rs b/examples/legacy/pokemon-service-tls/tests/custom_connectors.rs new file mode 100644 index 00000000000..a65881afe10 --- /dev/null +++ b/examples/legacy/pokemon-service-tls/tests/custom_connectors.rs @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +pub mod common; + +use serial_test::serial; + +// This test invokes an operation with a client that can only send HTTP2 requests and whose TLS +// implementation is backed by `rustls`. +#[tokio::test] +#[serial] +async fn test_do_nothing_http2_rustls_connector() { + let _child = common::run_server().await; + let client = common::client_http2_only(); + + let _check_health = client.do_nothing().send().await.unwrap(); +} + +// This test invokes an operation with a client whose TLS implementation is backed by `native_tls`. +#[tokio::test] +#[serial] +async fn test_do_nothing_native_tls_connector() { + let _child = common::run_server().await; + let client = common::native_tls_client(); + + let _check_health = client.do_nothing().send().await.unwrap(); +} diff --git a/examples/legacy/pokemon-service-tls/tests/testdata/localhost.crt b/examples/legacy/pokemon-service-tls/tests/testdata/localhost.crt new file mode 100644 index 00000000000..eecdc6dc8c2 --- /dev/null +++ b/examples/legacy/pokemon-service-tls/tests/testdata/localhost.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFGTCCAwGgAwIBAgIUN/FD3OayKwJt9hXNKo4JKxqFSK4wDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMDgxNzE1MjQzMFoXDTMyMDgx +NDE1MjQzMFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEAulMGcyA69ioNMT8Kz0CdP2QP5elLNnltBykoqoJwbvKS +94+l5XA//29M4NpLphHcDxNXx3qB318bixUIPBtu66OiIsTGX8yrYPA4IO3Xt5/2 +wp2z1lNLouyW1+gPaPjKzcrjnHmqHS90CFDQqxdv9I0rIFIQ+U5hm5T9Hjr5xs36 +43l2FXAjeigoEuwtVBDt44yhEyeLSDwFJES3sH73AvpruMdxGv2KDVN4whuajWll +RLTqpqBvVSM6JbaV/VD2simpZeolSl8yKIenM2PWPdLIHSMEBg6IaYgpSpzoyvmh +089peAaiJfVrN53QjqDVyaN5os9ST03ZEzXQUI38lpvWGmV9Tcs5WfidLA1EbPjv +yE1zBbZh0SrP/+EALwkoIRslI8DXvz/9U5Cq7q9U4OHjWB+yjE5/BX6o6hfrqfJ1 +Ldg2fTp/TYEudmefM8eRzx6sdYtTPZBrSpkRgvmxd+6k3QUtsAQhtBTMpvJpWsgs +sD7Uo6G2JRag53oT/2cxG03Qy5HqySZUK1bpFW03W5FL3Pq6AkpGy1hnSxlifkHp +si61dbjCV5uRdxRCLyH9fD3HImecet+vnuZlvsP0MAzh0vbli/dcFZ7xUoSqFWnj +egnPohdOmF6C8kXvWBt51N4jjW+eLxPAr9H0mJtdIvEHWBNNW9iitzGz5Gw0g4sC +AwEAAaNjMGEwHQYDVR0OBBYEFEoLkB78Z6jgPPmOyf0XnWo/LjA9MB8GA1UdIwQY +MBaAFEoLkB78Z6jgPPmOyf0XnWo/LjA9MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAJ +BgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQC17OljBEEVYefzk2mwg20AXDtL +PUJ46hLrUM7BcNBjd8AbtrLH/pdCRCexnv7tzYbwMhDNdqHiIcXDHEMNP3gXryB2 +ckU5ms/LzfKADM2/hrDZiR03XYSL4thjFkQNVfYnk9k7LTv9pKW0b+J2OrMun7+w +bdXcNw+igvnYiBgNJRo0IC9O5nejqLGWwBfveAJPetxjy6PvBkLqgIw2glivmTrh +Kdoq/I2/ZcxT0GyhEVIHP9W8Hh5goNm+RbsB/hDYhK+5s2+rL1lwJrwhNBrHhG1u +CtYmd2rD0J/mGf1cAw7t+hmwW0O7J9BVZw4YL/m4vDAsTO4zaeoAvDwsgQwPzPF1 +rmRtV+7jJHyIP/b021XIdIZU5KsXCCA3+B31mHJF1GLreG7WI+wClRsiNSbP7Zuw +OnUOTDZc77Y4oaDKl0UL8tz1GNwX5G9U5h+FciTPKCtg1gGiqSkB/3BOON2WaVOb +6Di9iAoH+dIjvWR/7ez7DAk/ITpGvBXS5RqaIXfB9pSJlVYsGp03ikgng1eJdXy4 +57XZnd47upHH88NTvIH9G/iOXQQCzF3MQXOqrJ/gem3ICeelvOoyNseHLvi8ZEqa +s693CJWaQAK/jD1mhka7yQzmb/Y1I53crc2UqSxX4FqFYP8xymza4Cg/E6pPJerG +LE/drJtbrIHTUlJB2Q== +-----END CERTIFICATE----- diff --git a/examples/legacy/pokemon-service-tls/tests/testdata/localhost.key b/examples/legacy/pokemon-service-tls/tests/testdata/localhost.key new file mode 100644 index 00000000000..6a8cc7f9bea --- /dev/null +++ b/examples/legacy/pokemon-service-tls/tests/testdata/localhost.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC6UwZzIDr2Kg0x +PwrPQJ0/ZA/l6Us2eW0HKSiqgnBu8pL3j6XlcD//b0zg2kumEdwPE1fHeoHfXxuL +FQg8G27ro6IixMZfzKtg8Dgg7de3n/bCnbPWU0ui7JbX6A9o+MrNyuOceaodL3QI +UNCrF2/0jSsgUhD5TmGblP0eOvnGzfrjeXYVcCN6KCgS7C1UEO3jjKETJ4tIPAUk +RLewfvcC+mu4x3Ea/YoNU3jCG5qNaWVEtOqmoG9VIzoltpX9UPayKall6iVKXzIo +h6czY9Y90sgdIwQGDohpiClKnOjK+aHTz2l4BqIl9Ws3ndCOoNXJo3miz1JPTdkT +NdBQjfyWm9YaZX1NyzlZ+J0sDURs+O/ITXMFtmHRKs//4QAvCSghGyUjwNe/P/1T +kKrur1Tg4eNYH7KMTn8FfqjqF+up8nUt2DZ9On9NgS52Z58zx5HPHqx1i1M9kGtK +mRGC+bF37qTdBS2wBCG0FMym8mlayCywPtSjobYlFqDnehP/ZzEbTdDLkerJJlQr +VukVbTdbkUvc+roCSkbLWGdLGWJ+QemyLrV1uMJXm5F3FEIvIf18PcciZ5x636+e +5mW+w/QwDOHS9uWL91wVnvFShKoVaeN6Cc+iF06YXoLyRe9YG3nU3iONb54vE8Cv +0fSYm10i8QdYE01b2KK3MbPkbDSDiwIDAQABAoICAAvSJaLF2jJw44pgILGaZ1Tf +ZnTPKBLqLDpxPYpny8tLf3sjoBeeLKk/ffChWNL4khiwwPe/tB/1muaS1zASYNH5 +UoQt2L9jhEHvq5fx5FGFiAm700OB4Fa9939LfTgghKP+vxGtKazqrEwKGIWqRH45 +kJFfM4LQRWKyAUcFiyrg5DhspcsMD2wkwmTE8Bvua7FCjvDgqDZVJycFvGOprRvW +wwvON2+fbek/hktGULgFBkQ6zXefI8ESgudj80Bxfl06RcGDU99T38zwzPD2i1/m +ZgTB38j562Sf8K1c/BXt4CWdzz1VVRHfGptvheJD85xJz0yUJk7atllrfMOyO7fp +4nj6M4EGZGfqqM6CFULkspVSoza/nLN3sOkcZqG+EJ9x6bo/MfUudJ50+cq2BhlQ +jM43j+wtm9DYPnJNXIC5FCze41N5MSDfK9h2oC16E6H6/VG9Y+AMMVrEDvsXXuOi +I0G8rcVanBdS3+nmmbTt4n0EVBLujB/ZJ/Qhsz/7QEeWn/xQNT4i00yRGG1mYJG0 +Ps0cy6t6jVrRoZmf7aYcUat97vHEP/ddo2V6ANRiZR3wVjhhoX1lVC8T0llzjxr4 +FEIDDuS+fnFqK1uHGBxS4lPHy/57gpdpYskoQtykpXURh4k39Fc28mzxKsrBhX6V +qY07bpgMNqYPC7SpkzO1AoIBAQDxEsGrZl0gNPhkXUwRSFvQxQDh0jqZAnEHdqOA +nO49z7ym7e/LELtq7y/HP9sZxoVsAcOryGL0qUpFrQozXMnSzWwqkxwOIABpQ4gq +mSJIZAUFVnV7m5h5xdln2jJ+xhvKv2vnXyuP3wRkiKrQPMqe6jE93cJb4YcMTK2V +xgxcUTZjT5LoMUCZguT1LCT/xR66epfombhGEweeTHJKEwPbwq1HbOECsB8vjZ8G +nwlm/Dt1fJXIo/+dvnfM+v79ebxKzC3t900Nj2eSCsX0bIU76zc1dqj+V/PD4+6h +NojOFrAusVaaOj5ssTTzebBqsmHiOs1a4YR5MOYidPpqvZ+9AoIBAQDF3HHwiiUp +zit5oIUkz1EkN7+jgEfrLNd9Kt3kNz3rTwXWoCE8tE4ctxBdn61RD3CHaT6PThNg +6naENyTFcjrP4F0O0K76ErlYxNSoV7w/OyrRmRu21U4gTF9nWidxOSTOo1qGJdKI +baAk4tSFsjsdysx9xcLueqDQdGOobzeSBr6tJSq8cvEvW39E6cNHDxVk5CEg0Ffq +7XA8+l+LfoP+6YL2du5jEe0K+/dTt2vYch8/9DloRezga21kV7Jea68Mqcxb5xsB +Coh5pe3OipUtaAWe6G+J1pRuz9OldacI36VuHQa/YBI7Ws7dt3IhPQoHnh0qujYp +iasxJQLH5ODnAoIBAEYBE1pJfGt41lSWvxsZrwfd3Va2LKv4CIiJTAtyBsDOTVMQ +Lx0Bu9reoDo08dP3URE/JeoBY7L2Ygn/qMGnhTgAzRND6tazNkta//SWyVzKJqcZ +Jz6AvXNHH83Hj/g+YR2sHpJukYDS2zyybx/PN2uUSD5V4jW6NPQ+Y/3lJ/u63ZdT +KS7h9oddek0zx366aCTwqqIx2VAIAKNYQav+/5TWYGkoVeLo7/VoI7DRh/Ju9nk0 +d25vKTBOeg19KYTD0AjMZ939fVOdvA6tsDQ9OydeM4cD8SkCs1fEHayU4H8wGXNF +rgdVOIFpqB23zaH+MOx39OAaMtTafUmuPHW4oOUCggEAe/jm70cvh+UlOl0Ib4ry +lVXU3nYXGdSL5GJCi6bNRi3KQ7MrgCSdOMK/H1pYNw0MfdvElffejn/56FfA03IC +RZOX2xuINyoaNfOGJ0Bps9i3uIJNah52iCgyMsi7I+chF9QkeR8jrdW6XMI/VNHa +1ozl2fxaaiAtuM7kTnn5AKb3O/eoslD2q6yRrrUlZNWfmwqRc0T3gTxqcdqSmQ2Z +WNQo+ZKFRU/LDXHYgvzPNtwylljIy3vcsrS84v1LxnuEP9P4NrE0K0/VORttSFdu +pvehZfLPSDdJ47CWNPrlwNqYhcjsHGbupX/9U9CIUykyqpk4PzhTjW0z9WPyPRs8 +iwKCAQEAsQRYdefBm/lYil70rlHvgxOvoCf8wTy6kiUTHFMZWUcbPB9+5C8HRRVu +kg+QTFn502H6gZhs3VkzpE4y1tClOe0s0HAfdBNfjP1Kk8i54hYOUzu0RAlOg4t+ +DcUBSmeXgXbYtzKLb2WqifTjOtuBYD515vOtcIM/19EaAMeccH0yWcvWDwFJu0jN +6DXUPTwIetMnmui5X1oFVgu9XDdXmhC7mFvMtaADHhh37hNqDlKDYpHQMMEJT/cT +WJvTCDK6nLkAYltPwehV74v2BEVknk0GHP1IcCLOjv6v3c1kt0TPZtnUr8pIfZGi +M8nPgza9amAhHxA8xPQgBs3l8d6k3w== +-----END PRIVATE KEY----- diff --git a/examples/legacy/pokemon-service/Cargo.toml b/examples/legacy/pokemon-service/Cargo.toml new file mode 100644 index 00000000000..eeda5a93860 --- /dev/null +++ b/examples/legacy/pokemon-service/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "pokemon-service" +version = "0.1.0" +edition = "2021" +publish = false +authors = ["Smithy-rs Server Team "] +description = "A smithy Rust service to retrieve information about Pokémon." + +[dependencies] +clap = { version = "4", features = ["derive"] } +http = "0.2" +hyper = { version = "0.14.26", features = ["server"] } +tokio = "1.26.0" +tower = "0.4" +tracing = "0.1" + +# Local paths +pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/", package = "pokemon-service-server-sdk-http0x", features = ["request-id"]} +pokemon-service-common = { path = "../pokemon-service-common/" } + +[dev-dependencies] +assert_cmd = "2.0" +async-stream = "0.3" +rand = "0.8.5" +serial_test = "3.1.1" + +# We use hyper client in tests +hyper = { version = "0.14.26", features = ["server", "client"] } + +# This dependency is only required for testing the `pokemon-service-tls` program. +hyper-rustls = { version = "0.24", features = ["http2"] } + +# Local paths +aws-smithy-legacy-http = { path = "../../../rust-runtime/aws-smithy-legacy-http/" } +pokemon-service-client = { path = "../pokemon-service-client/", package = "pokemon-service-client-http0x", features = [ + "behavior-version-latest", +] } diff --git a/examples/legacy/pokemon-service/src/authz.rs b/examples/legacy/pokemon-service/src/authz.rs new file mode 100644 index 00000000000..51a1c82e526 --- /dev/null +++ b/examples/legacy/pokemon-service/src/authz.rs @@ -0,0 +1,219 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! This file showcases a rather minimal model plugin that is agnostic over the operation that it +//! is applied to. +//! +//! It is interesting because it is not trivial to figure out how to write one. As the +//! documentation for [`aws_smithy_http_server::plugin::ModelMarker`] calls out, most model +//! plugins' implementation are _operation-specific_, which are simpler. + +use std::{marker::PhantomData, pin::Pin}; + +use pokemon_service_server_sdk::server::{ + body::BoxBody, + operation::OperationShape, + plugin::{ModelMarker, Plugin}, + response::IntoResponse, +}; +use tower::Service; + +pub struct AuthorizationPlugin { + // Private so that users are forced to use the `new` constructor. + _private: (), +} + +impl AuthorizationPlugin { + pub fn new() -> Self { + Self { _private: () } + } +} + +/// `T` is the inner service this plugin is applied to. +/// See the documentation for [`Plugin`] for details. +impl Plugin for AuthorizationPlugin { + type Output = AuthorizeService; + + fn apply(&self, input: T) -> Self::Output { + AuthorizeService { + inner: input, + authorizer: Authorizer::new(), + } + } +} + +impl ModelMarker for AuthorizationPlugin {} + +pub struct AuthorizeService { + inner: S, + authorizer: Authorizer, +} + +/// We manually implement `Clone` instead of adding `#[derive(Clone)]` because we don't require +/// `Op` to be cloneable. +impl Clone for AuthorizeService +where + S: Clone, +{ + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + authorizer: self.authorizer.clone(), + } + } +} + +/// The error returned by [`AuthorizeService`]. +pub enum AuthorizeServiceError { + /// Authorization was successful, but the inner service yielded an error. + InnerServiceError(E), + /// Authorization was not successful. + AuthorizeError { message: String }, +} + +// Only the _outermost_ model plugin needs to apply a `Service` whose error type implements +// `IntoResponse` for the protocol the service uses (this requirement comes from the `Service` +// implementation of [`aws_smithy_http_server::operation::Upgrade`]). So if the model plugin is +// meant to be applied in any position, and to any Smithy service, one should implement +// `IntoResponse` for all protocols. +// +// Having model plugins apply a `Service` that has a `Service::Response` type or a `Service::Error` +// type that is different from those returned by the inner service hence diminishes the reusability +// of the plugin because it makes the plugin less composable. Most plugins should instead work with +// the inner service's types, and _at most_ require that those be `Op::Input` and `Op::Error`, for +// maximum composability: +// +// ``` +// ... +// where +// S: Service<(Op::Input, ($($var,)*)), Error = Op::Error> +// ... +// { +// type Response = S::Response; +// type Error = S::Error; +// type Future = Pin> + Send>>; +// } +// +// ``` +// +// This plugin still exemplifies how changing a type can be done to make it more interesting. + +impl IntoResponse

for AuthorizeServiceError +where + E: IntoResponse

, +{ + fn into_response(self) -> http::Response { + match self { + AuthorizeServiceError::InnerServiceError(e) => e.into_response(), + AuthorizeServiceError::AuthorizeError { message } => http::Response::builder() + .status(http::StatusCode::UNAUTHORIZED) + .body(pokemon_service_server_sdk::server::body::to_boxed(message)) + .expect("attempted to build an invalid HTTP response; please file a bug report"), + } + } +} + +macro_rules! impl_service { + ($($var:ident),*) => { + impl Service<(Op::Input, ($($var,)*))> for AuthorizeService + where + S: Service<(Op::Input, ($($var,)*)), Error = Op::Error> + Clone + Send + 'static, + S::Future: Send, + Op: OperationShape + Send + Sync + 'static, + Op::Input: Send + Sync + 'static, + $($var: Send + 'static,)* + { + type Response = S::Response; + type Error = AuthorizeServiceError; + type Future = + Pin> + Send>>; + + fn poll_ready( + &mut self, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.inner + .poll_ready(cx) + .map_err(|e| Self::Error::InnerServiceError(e)) + } + + fn call(&mut self, req: (Op::Input, ($($var,)*))) -> Self::Future { + let (input, exts) = req; + + // Replacing the service is necessary to avoid readiness problems. + // https://docs.rs/tower/latest/tower/trait.Service.html#be-careful-when-cloning-inner-services + let service = self.inner.clone(); + let mut service = std::mem::replace(&mut self.inner, service); + + let authorizer = self.authorizer.clone(); + + let fut = async move { + let is_authorized = authorizer.authorize(&input).await; + if !is_authorized { + return Err(Self::Error::AuthorizeError { + message: "Not authorized!".to_owned(), + }); + } + + service + .call((input, exts)) + .await + .map_err(|e| Self::Error::InnerServiceError(e)) + }; + Box::pin(fut) + } + } + }; +} + +struct Authorizer { + operation: PhantomData, +} + +/// We manually implement `Clone` instead of adding `#[derive(Clone)]` because we don't require +/// `Op` to be cloneable. +impl Clone for Authorizer { + fn clone(&self) -> Self { + Self { + operation: PhantomData, + } + } +} + +impl Authorizer { + fn new() -> Self { + Self { + operation: PhantomData, + } + } + + async fn authorize(&self, _input: &Op::Input) -> bool + where + Op: OperationShape, + { + // We'd perform the actual authorization here. + // We would likely need to add bounds on `Op::Input`, `Op::Error`, if we wanted to do + // anything useful. + true + } +} + +// If we want our plugin to be as reusable as possible, the service it applies should work with +// inner services (i.e. operation handlers) that take a variable number of parameters. A Rust macro +// is helpful in providing those implementations concisely. +// Each handler function registered must accept the operation's input type (if there is one). +// Additionally, it can take up to 7 different parameters, each of which must implement the +// `FromParts` trait. To ensure that this `AuthorizeService` works with any of those inner +// services, we must implement it to handle up to +// 7 different types. Therefore, we invoke the `impl_service` macro 8 times. + +impl_service!(); +impl_service!(T1); +impl_service!(T1, T2); +impl_service!(T1, T2, T3); +impl_service!(T1, T2, T3, T4); +impl_service!(T1, T2, T3, T4, T5); +impl_service!(T1, T2, T3, T4, T5, T6); +impl_service!(T1, T2, T3, T4, T5, T6, T7); diff --git a/examples/legacy/pokemon-service/src/lib.rs b/examples/legacy/pokemon-service/src/lib.rs new file mode 100644 index 00000000000..95341abd9fe --- /dev/null +++ b/examples/legacy/pokemon-service/src/lib.rs @@ -0,0 +1,59 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::net::{IpAddr, SocketAddr}; + +use pokemon_service_server_sdk::{ + error::{GetStorageError, StorageAccessNotAuthorized}, + input::{DoNothingInput, GetStorageInput}, + output::{DoNothingOutput, GetStorageOutput}, + server::request::{connect_info::ConnectInfo, request_id::ServerRequestId}, +}; + +// Defaults shared between `main.rs` and `/tests`. +pub const DEFAULT_ADDRESS: &str = "127.0.0.1"; +pub const DEFAULT_PORT: u16 = 13734; + +/// Logs the request IDs to `DoNothing` operation. +pub async fn do_nothing_but_log_request_ids( + _input: DoNothingInput, + request_id: ServerRequestId, +) -> DoNothingOutput { + tracing::debug!(%request_id, "do nothing"); + DoNothingOutput {} +} + +/// Retrieves the user's storage. No authentication required for locals. +pub async fn get_storage_with_local_approved( + input: GetStorageInput, + connect_info: ConnectInfo, +) -> Result { + tracing::debug!("attempting to authenticate storage user"); + + if !(input.user == "ash" && input.passcode == "pikachu123") { + tracing::debug!("authentication failed"); + return Err(GetStorageError::StorageAccessNotAuthorized( + StorageAccessNotAuthorized {}, + )); + } + + // We support trainers in our local gym + let local = connect_info.0.ip() == "127.0.0.1".parse::().unwrap(); + if local { + tracing::info!("welcome back"); + return Ok(GetStorageOutput { + collection: vec![ + String::from("bulbasaur"), + String::from("charmander"), + String::from("squirtle"), + String::from("pikachu"), + ], + }); + } + + Ok(GetStorageOutput { + collection: vec![String::from("pikachu")], + }) +} diff --git a/examples/legacy/pokemon-service/src/main.rs b/examples/legacy/pokemon-service/src/main.rs new file mode 100644 index 00000000000..16045350405 --- /dev/null +++ b/examples/legacy/pokemon-service/src/main.rs @@ -0,0 +1,115 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +mod authz; +mod plugin; + +use std::{net::SocketAddr, sync::Arc}; + +use clap::Parser; +use pokemon_service_server_sdk::server::{ + extension::OperationExtensionExt, + instrumentation::InstrumentExt, + layer::alb_health_check::AlbHealthCheckLayer, + plugin::{HttpPlugins, ModelPlugins, Scoped}, + request::request_id::ServerRequestIdProviderLayer, + AddExtensionLayer, +}; + +use hyper::StatusCode; +use plugin::PrintExt; + +use pokemon_service::{ + do_nothing_but_log_request_ids, get_storage_with_local_approved, DEFAULT_ADDRESS, DEFAULT_PORT, +}; +use pokemon_service_common::{ + capture_pokemon, check_health, get_pokemon_species, get_server_statistics, setup_tracing, + stream_pokemon_radio, State, +}; +use pokemon_service_server_sdk::{scope, PokemonService, PokemonServiceConfig}; + +use crate::authz::AuthorizationPlugin; + +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Args { + /// Hyper server bind address. + #[clap(short, long, action, default_value = DEFAULT_ADDRESS)] + address: String, + /// Hyper server bind port. + #[clap(short, long, action, default_value_t = DEFAULT_PORT)] + port: u16, +} + +#[tokio::main] +pub async fn main() { + let args = Args::parse(); + setup_tracing(); + + scope! { + /// A scope containing `GetPokemonSpecies` and `GetStorage`. + struct PrintScope { + includes: [GetPokemonSpecies, GetStorage] + } + } + + // Scope the `PrintPlugin`, defined in `plugin.rs`, to `PrintScope`. + let print_plugin = Scoped::new::(HttpPlugins::new().print()); + + let http_plugins = HttpPlugins::new() + // Apply the scoped `PrintPlugin` + .push(print_plugin) + // Apply the `OperationExtensionPlugin` defined in `aws_smithy_http_server::extension`. This allows other + // plugins or tests to access a `aws_smithy_http_server::extension::OperationExtension` from + // `Response::extensions`, or infer routing failure when it's missing. + .insert_operation_extension() + // Adds `tracing` spans and events to the request lifecycle. + .instrument(); + + let authz_plugin = AuthorizationPlugin::new(); + let model_plugins = ModelPlugins::new().push(authz_plugin); + + let config = PokemonServiceConfig::builder() + // Set up shared state and middlewares. + .layer(AddExtensionLayer::new(Arc::new(State::default()))) + // Handle `/ping` health check requests. + .layer(AlbHealthCheckLayer::from_handler("/ping", |_req| async { + StatusCode::OK + })) + // Add server request IDs. + .layer(ServerRequestIdProviderLayer::new()) + .http_plugin(http_plugins) + .model_plugin(model_plugins) + .build(); + + let app = PokemonService::builder(config) + // Build a registry containing implementations to all the operations in the service. These + // are async functions or async closures that take as input the operation's input and + // return the operation's output. + .get_pokemon_species(get_pokemon_species) + .get_storage(get_storage_with_local_approved) + .get_server_statistics(get_server_statistics) + .capture_pokemon(capture_pokemon) + .do_nothing(do_nothing_but_log_request_ids) + .check_health(check_health) + .stream_pokemon_radio(stream_pokemon_radio) + .build() + .expect("failed to build an instance of PokemonService"); + + // Using `into_make_service_with_connect_info`, rather than `into_make_service`, to adjoin the `SocketAddr` + // connection info. + let make_app = app.into_make_service_with_connect_info::(); + + // Bind the application to a socket. + let bind: SocketAddr = format!("{}:{}", args.address, args.port) + .parse() + .expect("unable to parse the server bind address and port"); + let server = hyper::Server::bind(&bind).serve(make_app); + + // Run forever-ish... + if let Err(err) = server.await { + eprintln!("server error: {err}"); + } +} diff --git a/examples/legacy/pokemon-service/src/plugin.rs b/examples/legacy/pokemon-service/src/plugin.rs new file mode 100644 index 00000000000..a1eec0d6a69 --- /dev/null +++ b/examples/legacy/pokemon-service/src/plugin.rs @@ -0,0 +1,81 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Provides an example [`Plugin`] implementation - [`PrintPlugin`]. + +use pokemon_service_server_sdk::server::{ + operation::OperationShape, + plugin::{HttpMarker, HttpPlugins, Plugin, PluginStack}, + service::ServiceShape, + shape_id::ShapeId, +}; +use tower::Service; + +use std::task::{Context, Poll}; + +/// A [`Service`] that prints a given string. +#[derive(Clone, Debug)] +pub struct PrintService { + inner: S, + operation_id: ShapeId, + service_id: ShapeId, +} + +impl Service for PrintService +where + S: Service, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + self.inner.poll_ready(cx) + } + + fn call(&mut self, req: R) -> Self::Future { + println!( + "Hi {} in {}", + self.operation_id.absolute(), + self.service_id.absolute() + ); + self.inner.call(req) + } +} +/// A [`Plugin`] for a service builder to add a [`PrintLayer`] over operations. +#[derive(Debug)] +pub struct PrintPlugin; + +impl Plugin for PrintPlugin +where + Ser: ServiceShape, + Op: OperationShape, +{ + type Output = PrintService; + + fn apply(&self, inner: T) -> Self::Output { + PrintService { + inner, + operation_id: Op::ID, + service_id: Ser::ID, + } + } +} + +impl HttpMarker for PrintPlugin {} + +/// This provides a [`print`](PrintExt::print) method on [`HttpPlugins`]. +pub trait PrintExt { + /// Causes all operations to print the operation name when called. + /// + /// This works by applying the [`PrintPlugin`]. + fn print(self) -> HttpPlugins>; +} + +impl PrintExt for HttpPlugins { + fn print(self) -> HttpPlugins> { + self.push(PrintPlugin) + } +} diff --git a/examples/legacy/pokemon-service/tests/common/mod.rs b/examples/legacy/pokemon-service/tests/common/mod.rs new file mode 100644 index 00000000000..2d58f4a975a --- /dev/null +++ b/examples/legacy/pokemon-service/tests/common/mod.rs @@ -0,0 +1,33 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use std::{process::Command, time::Duration}; + +use assert_cmd::prelude::*; +use tokio::time::sleep; + +use pokemon_service::{DEFAULT_ADDRESS, DEFAULT_PORT}; +use pokemon_service_client::{Client, Config}; +use pokemon_service_common::ChildDrop; + +pub async fn run_server() -> ChildDrop { + let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); + let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); + + sleep(Duration::from_millis(500)).await; + + ChildDrop(child) +} + +pub fn base_url() -> String { + format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}") +} + +pub fn client() -> Client { + let config = Config::builder() + .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}")) + .build(); + Client::from_conf(config) +} diff --git a/examples/legacy/pokemon-service/tests/event_streaming.rs b/examples/legacy/pokemon-service/tests/event_streaming.rs new file mode 100644 index 00000000000..664827620bb --- /dev/null +++ b/examples/legacy/pokemon-service/tests/event_streaming.rs @@ -0,0 +1,162 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +pub mod common; + +use async_stream::stream; +use rand::Rng; +use serial_test::serial; + +use pokemon_service_client::types::{ + error::{AttemptCapturingPokemonEventError, MasterBallUnsuccessful}, + AttemptCapturingPokemonEvent, CapturingEvent, CapturingPayload, +}; + +fn get_pokemon_to_capture() -> String { + let pokemons = vec!["Charizard", "Pikachu", "Regieleki"]; + pokemons[rand::thread_rng().gen_range(0..pokemons.len())].to_string() +} + +fn get_pokeball() -> String { + let random = rand::thread_rng().gen_range(0..100); + let pokeball = if random < 5 { + "Master Ball" + } else if random < 30 { + "Great Ball" + } else if random < 80 { + "Fast Ball" + } else { + "Smithy Ball" + }; + pokeball.to_string() +} + +#[tokio::test] +#[serial] +async fn event_stream_test() { + let _child = common::run_server().await; + let client = common::client(); + + let mut team = vec![]; + let input_stream = stream! { + // Always Pikachu + yield Ok(AttemptCapturingPokemonEvent::Event( + CapturingEvent::builder() + .payload(CapturingPayload::builder() + .name("Pikachu") + .pokeball("Master Ball") + .build()) + .build() + )); + yield Ok(AttemptCapturingPokemonEvent::Event( + CapturingEvent::builder() + .payload(CapturingPayload::builder() + .name("Regieleki") + .pokeball("Fast Ball") + .build()) + .build() + )); + yield Err(AttemptCapturingPokemonEventError::MasterBallUnsuccessful(MasterBallUnsuccessful::builder().build())); + // The next event should not happen + yield Ok(AttemptCapturingPokemonEvent::Event( + CapturingEvent::builder() + .payload(CapturingPayload::builder() + .name("Charizard") + .pokeball("Great Ball") + .build()) + .build() + )); + }; + + // Throw many! + let mut output = common::client() + .capture_pokemon() + .region("Kanto") + .events(input_stream.into()) + .send() + .await + .unwrap(); + loop { + match output.events.recv().await { + Ok(Some(capture)) => { + let pokemon = capture.as_event().unwrap().name.as_ref().unwrap().clone(); + let pokedex = capture + .as_event() + .unwrap() + .pokedex_update + .as_ref() + .unwrap() + .clone(); + let shiny = if *capture.as_event().unwrap().shiny.as_ref().unwrap() { + "" + } else { + "not " + }; + let expected_pokedex: Vec = (0..255).collect(); + println!("captured {} ({}shiny)", pokemon, shiny); + if expected_pokedex == pokedex.into_inner() { + println!("pokedex updated") + } + team.push(pokemon); + } + Err(e) => { + println!("error from the server: {:?}", e); + break; + } + Ok(None) => break, + } + } + + while team.len() < 6 { + let pokeball = get_pokeball(); + let pokemon = get_pokemon_to_capture(); + let input_stream = stream! { + yield Ok(AttemptCapturingPokemonEvent::Event( + CapturingEvent::builder() + .payload(CapturingPayload::builder() + .name(pokemon) + .pokeball(pokeball) + .build()) + .build() + )) + }; + let mut output = client + .capture_pokemon() + .region("Kanto") + .events(input_stream.into()) + .send() + .await + .unwrap(); + match output.events.recv().await { + Ok(Some(capture)) => { + let pokemon = capture.as_event().unwrap().name.as_ref().unwrap().clone(); + let pokedex = capture + .as_event() + .unwrap() + .pokedex_update + .as_ref() + .unwrap() + .clone(); + let shiny = if *capture.as_event().unwrap().shiny.as_ref().unwrap() { + "" + } else { + "not " + }; + let expected_pokedex: Vec = (0..255).collect(); + println!("captured {} ({}shiny)", pokemon, shiny); + if expected_pokedex == pokedex.into_inner() { + println!("pokedex updated") + } + team.push(pokemon); + } + Err(e) => { + println!("error from the server: {:?}", e); + break; + } + Ok(None) => {} + } + } + println!("Team: {:?}", team); +} diff --git a/examples/legacy/pokemon-service/tests/simple.rs b/examples/legacy/pokemon-service/tests/simple.rs new file mode 100644 index 00000000000..215ab25f9fe --- /dev/null +++ b/examples/legacy/pokemon-service/tests/simple.rs @@ -0,0 +1,128 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use bytes; +use http_body_util; +use hyper_util::{client::legacy::Client, rt::TokioExecutor}; +use pokemon_service_client::{ + error::{DisplayErrorContext, SdkError}, + operation::get_storage::GetStorageError, + types::error::StorageAccessNotAuthorized, +}; +use serial_test::serial; + +pub mod common; + +#[tokio::test] +#[serial] +async fn simple_integration_test() { + let _child = common::run_server().await; + let client = common::client(); + + let service_statistics_out = client.get_server_statistics().send().await.unwrap(); + assert_eq!(0, service_statistics_out.calls_count); + + let pokemon_species_output = client + .get_pokemon_species() + .name("pikachu") + .send() + .await + .unwrap(); + assert_eq!("pikachu", pokemon_species_output.name()); + + let service_statistics_out = client.get_server_statistics().send().await.unwrap(); + assert_eq!(1, service_statistics_out.calls_count); + + let storage_err = client + .get_storage() + .user("ash") + .passcode("pikachu321") + .send() + .await; + let has_not_authorized_error = if let Err(SdkError::ServiceError(context)) = storage_err { + matches!( + context.err(), + GetStorageError::StorageAccessNotAuthorized(StorageAccessNotAuthorized { .. }), + ) + } else { + false + }; + assert!(has_not_authorized_error, "expected NotAuthorized error"); + + let storage_out = client + .get_storage() + .user("ash") + .passcode("pikachu123") + .send() + .await + .unwrap(); + assert_eq!( + vec![ + "bulbasaur".to_string(), + "charmander".to_string(), + "squirtle".to_string(), + "pikachu".to_string() + ], + storage_out.collection + ); + + let pokemon_species_error = client + .get_pokemon_species() + .name("some_pokémon") + .send() + .await + .unwrap_err(); + let message = DisplayErrorContext(pokemon_species_error).to_string(); + let expected = + r#"ResourceNotFoundError [ResourceNotFoundException]: Requested Pokémon not available"#; + assert!( + message.contains(expected), + "expected '{message}' to contain '{expected}'" + ); + + let service_statistics_out = client.get_server_statistics().send().await.unwrap(); + assert_eq!(2, service_statistics_out.calls_count); + + let hyper_client = Client::builder(TokioExecutor::new()).build_http(); + let health_check_url = format!("{}/ping", common::base_url()); + let health_check_url = hyper::Uri::try_from(health_check_url).unwrap(); + let request = hyper::Request::builder() + .uri(health_check_url) + .body(http_body_util::Empty::::new()) + .unwrap(); + let result = hyper_client.request(request).await.unwrap(); + + assert_eq!(result.status(), 200); +} + +#[tokio::test] +#[serial] +async fn health_check() { + let _child = common::run_server().await; + + use pokemon_service::{DEFAULT_ADDRESS, DEFAULT_PORT}; + let url = format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}/ping"); + let uri = url.parse::().expect("invalid URL"); + + // Since the `/ping` route is not modeled in Smithy, we use a regular + // Hyper HTTP client to make a request to it. + let request = hyper::Request::builder() + .uri(uri) + .body(http_body_util::Empty::::new()) + .expect("failed to build request"); + + let client = Client::builder(TokioExecutor::new()).build_http(); + let response = client + .request(request) + .await + .expect("failed to get response"); + + assert_eq!(response.status(), hyper::StatusCode::OK); + let body = http_body_util::BodyExt::collect(response.into_body()) + .await + .expect("failed to read response body") + .to_bytes(); + assert!(body.is_empty()); +} diff --git a/examples/pokemon-service-client-usage/Cargo.toml b/examples/pokemon-service-client-usage/Cargo.toml index 290c8d80cb5..3bbefe25d05 100644 --- a/examples/pokemon-service-client-usage/Cargo.toml +++ b/examples/pokemon-service-client-usage/Cargo.toml @@ -15,25 +15,26 @@ publish = false # are specifically noted in comments above the corresponding dependency in this file. pokemon-service-client = { path = "../pokemon-service-client/", features = ["behavior-version-latest"] } -# Required for getting the operation name from the `Metadata`. -aws-smithy-http = { path = "../../rust-runtime/aws-smithy-http/" } - # Required for `Storable` and `StoreReplace` in `response-header-interceptor` example. aws-smithy-types = { path = "../../rust-runtime/aws-smithy-types/" } -# Required for `HyperClientBuilder` in `client-connector` example. +# Required for `Builder` in `client-connector` example. +aws-smithy-http-client = { path = "../../rust-runtime/aws-smithy-http-client/", features=["default-client", "rustls-aws-lc"] } + +# Required for test utilities in examples. aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime/", features=["test-util"] } # Required for `Metadata` in `custom-header-using-interceptor` example. aws-smithy-runtime-api = { path = "../../rust-runtime/aws-smithy-runtime-api/", features=["client"] } -hyper = { version = "0.14.25", features = ["client", "full"] } +hyper = { version = "1", features = ["client", "http1", "http2"] } +hyper-util = { version = "0.1", features = ["client", "client-legacy", "http1", "http2"] } tokio = {version = "1.26.0", features=["full"]} tracing = "0.1.37" tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } -rustls = "0.21.8" -hyper-rustls = "0.24.1" -http = "0.2.9" +rustls = "0.23" +hyper-rustls = "0.27" +http = "1" uuid = {version="1.4.1", features = ["v4"]} thiserror = "1.0.49" diff --git a/examples/pokemon-service-client-usage/examples/client-connector.rs b/examples/pokemon-service-client-usage/examples/client-connector.rs index b1a7ecef846..13f2e82540b 100644 --- a/examples/pokemon-service-client-usage/examples/client-connector.rs +++ b/examples/pokemon-service-client-usage/examples/client-connector.rs @@ -11,8 +11,7 @@ /// /// The example can be run using `cargo run --example client-connector`. /// -use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; -use hyper_rustls::ConfigBuilderExt; +use aws_smithy_http_client::{Builder, tls}; use pokemon_service_client::Client as PokemonClient; use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; @@ -26,25 +25,19 @@ use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL /// let client = create_client(); /// ``` fn create_client() -> PokemonClient { - let tls_config = rustls::ClientConfig::builder() - .with_safe_defaults() - // `with_native_roots()`: Load platform trusted root certificates. - // `with_webpki_roots()`: Load Mozilla’s set of trusted roots. - .with_native_roots() - // To use client side certificates, you can use - // `.with_client_auth_cert(client_cert, client_key)` instead of `.with_no_client_auth()` - .with_no_client_auth(); + // Create a TLS context that loads platform trusted root certificates. + // The TrustStore::default() enables native roots by default. + let tls_context = tls::TlsContext::builder() + .with_trust_store(tls::TrustStore::default()) + .build() + .expect("failed to build TLS context"); - let tls_connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config(tls_config) - // This can be changed to `.https_only()` to ensure that the client always uses HTTPs - .https_or_http() - .enable_http1() - .enable_http2() - .build(); - - // Create a hyper-based HTTP client that uses this TLS connector. - let http_client = HyperClientBuilder::new().build(tls_connector); + // Create an HTTP client using rustls with AWS-LC crypto provider. + // To use client side certificates, you would need to customize the TLS config further. + let http_client = Builder::new() + .tls_provider(tls::Provider::Rustls(tls::rustls_provider::CryptoMode::AwsLc)) + .tls_context(tls_context) + .build_https(); // Pass the smithy connector to the Client::ConfigBuilder let config = pokemon_service_client::Config::builder() diff --git a/examples/pokemon-service-client-usage/examples/mock-request.rs b/examples/pokemon-service-client-usage/examples/mock-request.rs index 5afafdaee14..eb7436c112a 100644 --- a/examples/pokemon-service-client-usage/examples/mock-request.rs +++ b/examples/pokemon-service-client-usage/examples/mock-request.rs @@ -12,7 +12,7 @@ /// /// The example can be run using `cargo run --example mock-request`. /// -use aws_smithy_runtime::client::http::test_util::capture_request; +use aws_smithy_http_client::test_util::capture_request; use pokemon_service_client::primitives::SdkBody; use pokemon_service_client::Client as PokemonClient; use pokemon_service_client_usage::{setup_tracing_subscriber, POKEMON_SERVICE_URL}; diff --git a/examples/pokemon-service-common/Cargo.toml b/examples/pokemon-service-common/Cargo.toml index 04cf0e8c1fd..8de6ca648d0 100644 --- a/examples/pokemon-service-common/Cargo.toml +++ b/examples/pokemon-service-common/Cargo.toml @@ -8,7 +8,7 @@ description = "A smithy Rust service to retrieve information about Pokémon." [dependencies] async-stream = "0.3" -http = "0.2.9" +http = "1" rand = "0.8" tracing = "0.1" tracing-subscriber = { version = "0.3.16", features = ["env-filter", "json"] } @@ -16,7 +16,8 @@ tokio = { version = "1", default-features = false, features = ["time"] } tower = "0.4" # Local paths -aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime", features = ["client", "connector-hyper-0-14-x", "tls-rustls"] } +aws-smithy-http-client = { path = "../../rust-runtime/aws-smithy-http-client", features = ["rustls-aws-lc"] } +aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime", features = ["client", "default-https-client"] } aws-smithy-runtime-api = { path = "../../rust-runtime/aws-smithy-runtime-api", features = ["client"] } pokemon-service-client = { path = "../pokemon-service-client/", features = [ "behavior-version-latest", diff --git a/examples/pokemon-service-common/src/lib.rs b/examples/pokemon-service-common/src/lib.rs index 16c25e02f55..ef231fd8bff 100644 --- a/examples/pokemon-service-common/src/lib.rs +++ b/examples/pokemon-service-common/src/lib.rs @@ -15,7 +15,7 @@ use std::{ }; use async_stream::stream; -use aws_smithy_runtime::client::http::hyper_014::HyperConnector; +use aws_smithy_http_client::{Connector, tls}; use aws_smithy_runtime_api::client::http::HttpConnector; use http::Uri; use pokemon_service_server_sdk::{ @@ -293,7 +293,7 @@ pub async fn capture_pokemon( } None => break, }, - Err(e) => println!("{:?}", e), + Err(e) => println!("{e:?}"), } } }; @@ -328,7 +328,9 @@ pub async fn stream_pokemon_radio( .parse::() .expect("Invalid url in `RADIO_STREAMS`"); - let connector = HyperConnector::builder().build_https(); + let connector = Connector::builder() + .tls_provider(tls::Provider::Rustls(tls::rustls_provider::CryptoMode::AwsLc)) + .build(); let result = connector .call( http::Request::builder() diff --git a/examples/pokemon-service-common/tests/plugins_execution_order.rs b/examples/pokemon-service-common/tests/plugins_execution_order.rs index 62fb47ed033..ee0fbad3526 100644 --- a/examples/pokemon-service-common/tests/plugins_execution_order.rs +++ b/examples/pokemon-service-common/tests/plugins_execution_order.rs @@ -46,7 +46,7 @@ async fn plugin_layers_are_executed_in_registration_order() { rcvr.expect_request() }; - app.call(request.try_into_http02x().unwrap()).await.unwrap(); + app.call(request.try_into().unwrap()).await.unwrap(); let output_guard = output.lock().unwrap(); assert_eq!(output_guard.deref(), &vec!["first", "second"]); diff --git a/examples/pokemon-service-lambda/Cargo.toml b/examples/pokemon-service-lambda/Cargo.toml index 21318a47525..96d64cab499 100644 --- a/examples/pokemon-service-lambda/Cargo.toml +++ b/examples/pokemon-service-lambda/Cargo.toml @@ -9,14 +9,12 @@ description = "A smithy Rust service to retrieve information about Pokémon via [dependencies] async-stream = "0.3.4" clap = { version = "4.1.11", features = ["derive"] } -hyper = {version = "0.14.26", features = ["server"] } +http = "1" +hyper = {version = "1", features = ["server"] } tokio = "1.26.0" tracing = "0.1" -# `aws-smithy-http-server` is only guaranteed to be compatible with this -# version of `lambda_http`, or semver-compatible versions of this version. -# Depending on other versions of `lambda_http` may not work. -lambda_http = "0.8.0" +lambda_http = "0.17" # Local paths pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/", features = ["aws-lambda"] } diff --git a/examples/pokemon-service-lambda/src/main.rs b/examples/pokemon-service-lambda/src/main.rs index a5c914534b9..93de83b2ede 100644 --- a/examples/pokemon-service-lambda/src/main.rs +++ b/examples/pokemon-service-lambda/src/main.rs @@ -41,6 +41,6 @@ pub async fn main() { let lambda = lambda_http::run(handler); if let Err(err) = lambda.await { - eprintln!("lambda error: {}", err); + eprintln!("lambda error: {err}"); } } diff --git a/examples/pokemon-service-server-skd-patch/Cargo.toml b/examples/pokemon-service-server-skd-patch/Cargo.toml new file mode 100644 index 00000000000..f68546b8ebe --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/Cargo.toml @@ -0,0 +1,63 @@ +# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +[package] +name = "pokemon-service-server-sdk" +version = "0.0.1" +authors = ["protocoltest@example.com"] +description = "test" +edition = "2021" + +[package.metadata.smithy] +codegen-version = "d4ac0215345535bd30b0e19b5b33ea4de8b1528c" +[dependencies.aws-smithy-eventstream] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-eventstream" +[dependencies.aws-smithy-http] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-http" +features = ["event-stream"] +[dependencies.aws-smithy-http-server] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-http-server" +[dependencies.aws-smithy-json] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-json" +[dependencies.aws-smithy-runtime-api] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-runtime-api" +features = ["http-1x"] +[dependencies.aws-smithy-types] +path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-types" +features = ["http-body-1-x"] +[dependencies.futures-util] +version = "0.3" +[dependencies.http] +version = "1" +[dependencies.mime] +version = "0.3" +[dependencies.nom] +version = "7" +[dependencies.percent-encoding] +version = "2.0.0" +[dependencies.pin-project-lite] +version = "0.2" +[dependencies.tower] +version = "0.4" +[dependencies.bytes] +version = "1" +[dependencies.http-body-1-0] +package = "http-body" +version = "1" +[dependencies.tracing] +version = "0.1" +# TODO: PATCH - http-body already exists as http-body-1-0, bytes already exists, hyper added for compatibility +[dependencies.hyper] +version = "1" +[dev-dependencies.hyper] +version = "1" +[dev-dependencies.hyper-util] +version = "0.1" +features = ["service"] +[dev-dependencies.tokio] +version = "1.23.1" +[features] +aws-lambda = ["aws-smithy-http-server/aws-lambda"] +request-id = ["aws-smithy-http-server/request-id"] +rt-tokio = ["aws-smithy-types/http-body-1-x", "aws-smithy-types/rt-tokio"] +default = ["request-id", "rt-tokio"] + + diff --git a/examples/pokemon-service-server-skd-patch/src/constrained.rs b/examples/pokemon-service-server-skd-patch/src/constrained.rs new file mode 100644 index 00000000000..b5f7300bd71 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/constrained.rs @@ -0,0 +1,16 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +pub(crate) trait Constrained { + type Unconstrained; +} + +#[derive(Debug, Clone)] +#[allow(dead_code)] +pub(crate) enum MaybeConstrained { + Constrained(T), + Unconstrained(T::Unconstrained), +} diff --git a/examples/pokemon-service-server-skd-patch/src/error.rs b/examples/pokemon-service-server-skd-patch/src/error.rs new file mode 100644 index 00000000000..263b4038eee --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/error.rs @@ -0,0 +1,885 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +/// Error type for the `GetStorage` operation. +/// Each variant represents an error that can occur for the `GetStorage` operation. +#[derive(::std::fmt::Debug)] +pub enum GetStorageError { + #[allow(missing_docs)] // documentation missing in model + ResourceNotFoundException(crate::error::ResourceNotFoundException), + /// Not authorized to access Pokémon storage. + StorageAccessNotAuthorized(crate::error::StorageAccessNotAuthorized), + /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. + ValidationException(crate::error::ValidationException), +} +impl ::std::fmt::Display for GetStorageError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + GetStorageError::ResourceNotFoundException(_inner) => _inner.fmt(f), + GetStorageError::StorageAccessNotAuthorized(_inner) => _inner.fmt(f), + GetStorageError::ValidationException(_inner) => _inner.fmt(f), + } + } +} +impl GetStorageError { + /// Returns `true` if the error kind is `GetStorageError::ResourceNotFoundException`. + pub fn is_resource_not_found_exception(&self) -> bool { + matches!(&self, GetStorageError::ResourceNotFoundException(_)) + } + /// Returns `true` if the error kind is `GetStorageError::StorageAccessNotAuthorized`. + pub fn is_storage_access_not_authorized(&self) -> bool { + matches!(&self, GetStorageError::StorageAccessNotAuthorized(_)) + } + /// Returns `true` if the error kind is `GetStorageError::ValidationException`. + pub fn is_validation_exception(&self) -> bool { + matches!(&self, GetStorageError::ValidationException(_)) + } + /// Returns the error name string by matching the correct variant. + pub fn name(&self) -> &'static str { + match &self { + GetStorageError::ResourceNotFoundException(_inner) => _inner.name(), + GetStorageError::StorageAccessNotAuthorized(_inner) => _inner.name(), + GetStorageError::ValidationException(_inner) => _inner.name(), + } + } +} +impl ::std::error::Error for GetStorageError { + fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { + match &self { + GetStorageError::ResourceNotFoundException(_inner) => Some(_inner), + GetStorageError::StorageAccessNotAuthorized(_inner) => Some(_inner), + GetStorageError::ValidationException(_inner) => Some(_inner), + } + } +} +impl ::std::convert::From + for crate::error::GetStorageError +{ + fn from(variant: crate::error::ResourceNotFoundException) -> crate::error::GetStorageError { + Self::ResourceNotFoundException(variant) + } +} +impl ::std::convert::From + for crate::error::GetStorageError +{ + fn from(variant: crate::error::StorageAccessNotAuthorized) -> crate::error::GetStorageError { + Self::StorageAccessNotAuthorized(variant) + } +} +impl ::std::convert::From for crate::error::GetStorageError { + fn from(variant: crate::error::ValidationException) -> crate::error::GetStorageError { + Self::ValidationException(variant) + } +} + +/// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct ValidationException { + /// A summary of the validation failure. + pub message: ::std::string::String, + /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. + pub field_list: ::std::option::Option<::std::vec::Vec>, +} +impl ValidationException { + /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. + pub fn field_list(&self) -> ::std::option::Option<&[crate::model::ValidationExceptionField]> { + self.field_list.as_deref() + } +} +impl ValidationException { + /// Returns the error message. + pub fn message(&self) -> &str { + &self.message + } + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "ValidationException" + } +} +impl ::std::fmt::Display for ValidationException { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "ValidationException")?; + { + ::std::write!(f, ": {}", &self.message)?; + } + Ok(()) + } +} +impl ::std::error::Error for ValidationException {} +impl ValidationException { + /// Creates a new builder-style object to manufacture [`ValidationException`](crate::error::ValidationException). + pub fn builder() -> crate::error::validation_exception::Builder { + crate::error::validation_exception::Builder::default() + } +} + +/// Not authorized to access Pokémon storage. +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct StorageAccessNotAuthorized {} +impl StorageAccessNotAuthorized { + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "StorageAccessNotAuthorized" + } +} +impl ::std::fmt::Display for StorageAccessNotAuthorized { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "StorageAccessNotAuthorized")?; + Ok(()) + } +} +impl ::std::error::Error for StorageAccessNotAuthorized {} +impl StorageAccessNotAuthorized { + /// Creates a new builder-style object to manufacture [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). + pub fn builder() -> crate::error::storage_access_not_authorized::Builder { + crate::error::storage_access_not_authorized::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct ResourceNotFoundException { + #[allow(missing_docs)] // documentation missing in model + pub message: ::std::string::String, +} +impl ResourceNotFoundException { + /// Returns the error message. + pub fn message(&self) -> &str { + &self.message + } + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "ResourceNotFoundException" + } +} +impl ::std::fmt::Display for ResourceNotFoundException { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "ResourceNotFoundException")?; + { + ::std::write!(f, ": {}", &self.message)?; + } + Ok(()) + } +} +impl ::std::error::Error for ResourceNotFoundException {} +impl ResourceNotFoundException { + /// Creates a new builder-style object to manufacture [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). + pub fn builder() -> crate::error::resource_not_found_exception::Builder { + crate::error::resource_not_found_exception::Builder::default() + } +} + +/// Error type for the `GetPokemonSpecies` operation. +/// Each variant represents an error that can occur for the `GetPokemonSpecies` operation. +#[derive(::std::fmt::Debug)] +pub enum GetPokemonSpeciesError { + #[allow(missing_docs)] // documentation missing in model + ResourceNotFoundException(crate::error::ResourceNotFoundException), + /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. + ValidationException(crate::error::ValidationException), +} +impl ::std::fmt::Display for GetPokemonSpeciesError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + GetPokemonSpeciesError::ResourceNotFoundException(_inner) => _inner.fmt(f), + GetPokemonSpeciesError::ValidationException(_inner) => _inner.fmt(f), + } + } +} +impl GetPokemonSpeciesError { + /// Returns `true` if the error kind is `GetPokemonSpeciesError::ResourceNotFoundException`. + pub fn is_resource_not_found_exception(&self) -> bool { + matches!(&self, GetPokemonSpeciesError::ResourceNotFoundException(_)) + } + /// Returns `true` if the error kind is `GetPokemonSpeciesError::ValidationException`. + pub fn is_validation_exception(&self) -> bool { + matches!(&self, GetPokemonSpeciesError::ValidationException(_)) + } + /// Returns the error name string by matching the correct variant. + pub fn name(&self) -> &'static str { + match &self { + GetPokemonSpeciesError::ResourceNotFoundException(_inner) => _inner.name(), + GetPokemonSpeciesError::ValidationException(_inner) => _inner.name(), + } + } +} +impl ::std::error::Error for GetPokemonSpeciesError { + fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { + match &self { + GetPokemonSpeciesError::ResourceNotFoundException(_inner) => Some(_inner), + GetPokemonSpeciesError::ValidationException(_inner) => Some(_inner), + } + } +} +impl ::std::convert::From + for crate::error::GetPokemonSpeciesError +{ + fn from( + variant: crate::error::ResourceNotFoundException, + ) -> crate::error::GetPokemonSpeciesError { + Self::ResourceNotFoundException(variant) + } +} +impl ::std::convert::From + for crate::error::GetPokemonSpeciesError +{ + fn from(variant: crate::error::ValidationException) -> crate::error::GetPokemonSpeciesError { + Self::ValidationException(variant) + } +} + +/// Error type for the `CapturePokemon` operation. +/// Each variant represents an error that can occur for the `CapturePokemon` operation. +#[derive(::std::fmt::Debug)] +pub enum CapturePokemonError { + #[allow(missing_docs)] // documentation missing in model + UnsupportedRegionError(crate::error::UnsupportedRegionError), + #[allow(missing_docs)] // documentation missing in model + ThrottlingError(crate::error::ThrottlingError), + /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. + ValidationException(crate::error::ValidationException), + #[allow(missing_docs)] // documentation missing in model + MasterBallUnsuccessful(crate::error::MasterBallUnsuccessful), + #[allow(missing_docs)] // documentation missing in model + InvalidPokeballError(crate::error::InvalidPokeballError), +} +impl ::std::fmt::Display for CapturePokemonError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + CapturePokemonError::UnsupportedRegionError(_inner) => _inner.fmt(f), + CapturePokemonError::ThrottlingError(_inner) => _inner.fmt(f), + CapturePokemonError::ValidationException(_inner) => _inner.fmt(f), + CapturePokemonError::MasterBallUnsuccessful(_inner) => _inner.fmt(f), + CapturePokemonError::InvalidPokeballError(_inner) => _inner.fmt(f), + } + } +} +impl CapturePokemonError { + /// Returns `true` if the error kind is `CapturePokemonError::UnsupportedRegionError`. + pub fn is_unsupported_region_error(&self) -> bool { + matches!(&self, CapturePokemonError::UnsupportedRegionError(_)) + } + /// Returns `true` if the error kind is `CapturePokemonError::ThrottlingError`. + pub fn is_throttling_error(&self) -> bool { + matches!(&self, CapturePokemonError::ThrottlingError(_)) + } + /// Returns `true` if the error kind is `CapturePokemonError::ValidationException`. + pub fn is_validation_exception(&self) -> bool { + matches!(&self, CapturePokemonError::ValidationException(_)) + } + /// Returns `true` if the error kind is `CapturePokemonError::MasterBallUnsuccessful`. + pub fn is_master_ball_unsuccessful(&self) -> bool { + matches!(&self, CapturePokemonError::MasterBallUnsuccessful(_)) + } + /// Returns `true` if the error kind is `CapturePokemonError::InvalidPokeballError`. + pub fn is_invalid_pokeball_error(&self) -> bool { + matches!(&self, CapturePokemonError::InvalidPokeballError(_)) + } + /// Returns the error name string by matching the correct variant. + pub fn name(&self) -> &'static str { + match &self { + CapturePokemonError::UnsupportedRegionError(_inner) => _inner.name(), + CapturePokemonError::ThrottlingError(_inner) => _inner.name(), + CapturePokemonError::ValidationException(_inner) => _inner.name(), + CapturePokemonError::MasterBallUnsuccessful(_inner) => _inner.name(), + CapturePokemonError::InvalidPokeballError(_inner) => _inner.name(), + } + } +} +impl ::std::error::Error for CapturePokemonError { + fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { + match &self { + CapturePokemonError::UnsupportedRegionError(_inner) => Some(_inner), + CapturePokemonError::ThrottlingError(_inner) => Some(_inner), + CapturePokemonError::ValidationException(_inner) => Some(_inner), + CapturePokemonError::MasterBallUnsuccessful(_inner) => Some(_inner), + CapturePokemonError::InvalidPokeballError(_inner) => Some(_inner), + } + } +} +impl ::std::convert::From + for crate::error::CapturePokemonError +{ + fn from(variant: crate::error::UnsupportedRegionError) -> crate::error::CapturePokemonError { + Self::UnsupportedRegionError(variant) + } +} +impl ::std::convert::From for crate::error::CapturePokemonError { + fn from(variant: crate::error::ThrottlingError) -> crate::error::CapturePokemonError { + Self::ThrottlingError(variant) + } +} +impl ::std::convert::From for crate::error::CapturePokemonError { + fn from(variant: crate::error::ValidationException) -> crate::error::CapturePokemonError { + Self::ValidationException(variant) + } +} +impl ::std::convert::From + for crate::error::CapturePokemonError +{ + fn from(variant: crate::error::MasterBallUnsuccessful) -> crate::error::CapturePokemonError { + Self::MasterBallUnsuccessful(variant) + } +} +impl ::std::convert::From + for crate::error::CapturePokemonError +{ + fn from(variant: crate::error::InvalidPokeballError) -> crate::error::CapturePokemonError { + Self::InvalidPokeballError(variant) + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct InvalidPokeballError { + #[allow(missing_docs)] // documentation missing in model + pub pokeball: ::std::string::String, +} +impl InvalidPokeballError { + #[allow(missing_docs)] // documentation missing in model + pub fn pokeball(&self) -> &str { + use std::ops::Deref; + self.pokeball.deref() + } +} +impl InvalidPokeballError { + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "InvalidPokeballError" + } +} +impl ::std::fmt::Display for InvalidPokeballError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "InvalidPokeballError")?; + Ok(()) + } +} +impl ::std::error::Error for InvalidPokeballError {} +impl InvalidPokeballError { + /// Creates a new builder-style object to manufacture [`InvalidPokeballError`](crate::error::InvalidPokeballError). + pub fn builder() -> crate::error::invalid_pokeball_error::Builder { + crate::error::invalid_pokeball_error::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct MasterBallUnsuccessful { + #[allow(missing_docs)] // documentation missing in model + pub message: ::std::option::Option<::std::string::String>, +} +impl MasterBallUnsuccessful { + /// Returns the error message. + pub fn message(&self) -> ::std::option::Option<&str> { + self.message.as_deref() + } + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "MasterBallUnsuccessful" + } +} +impl ::std::fmt::Display for MasterBallUnsuccessful { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "MasterBallUnsuccessful")?; + if let ::std::option::Option::Some(inner_1) = &self.message { + { + ::std::write!(f, ": {}", inner_1)?; + } + } + Ok(()) + } +} +impl ::std::error::Error for MasterBallUnsuccessful {} +impl MasterBallUnsuccessful { + /// Creates a new builder-style object to manufacture [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). + pub fn builder() -> crate::error::master_ball_unsuccessful::Builder { + crate::error::master_ball_unsuccessful::Builder::default() + } +} +impl crate::constrained::Constrained for crate::error::MasterBallUnsuccessful { + type Unconstrained = crate::error::master_ball_unsuccessful::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct ThrottlingError {} +impl ThrottlingError { + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "ThrottlingError" + } +} +impl ::std::fmt::Display for ThrottlingError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "ThrottlingError")?; + Ok(()) + } +} +impl ::std::error::Error for ThrottlingError {} +impl ThrottlingError { + /// Creates a new builder-style object to manufacture [`ThrottlingError`](crate::error::ThrottlingError). + pub fn builder() -> crate::error::throttling_error::Builder { + crate::error::throttling_error::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct UnsupportedRegionError { + #[allow(missing_docs)] // documentation missing in model + pub region: ::std::string::String, +} +impl UnsupportedRegionError { + #[allow(missing_docs)] // documentation missing in model + pub fn region(&self) -> &str { + use std::ops::Deref; + self.region.deref() + } +} +impl UnsupportedRegionError { + #[doc(hidden)] + /// Returns the error name. + pub fn name(&self) -> &'static str { + "UnsupportedRegionError" + } +} +impl ::std::fmt::Display for UnsupportedRegionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + ::std::write!(f, "UnsupportedRegionError")?; + Ok(()) + } +} +impl ::std::error::Error for UnsupportedRegionError {} +impl UnsupportedRegionError { + /// Creates a new builder-style object to manufacture [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). + pub fn builder() -> crate::error::unsupported_region_error::Builder { + crate::error::unsupported_region_error::Builder::default() + } +} + +/// Error type for the `CapturePokemonEvents` operation. +/// Each variant represents an error that can occur for the `CapturePokemonEvents` operation. +#[derive(::std::fmt::Debug)] +pub enum CapturePokemonEventsError { + #[allow(missing_docs)] // documentation missing in model + InvalidPokeballError(crate::error::InvalidPokeballError), + #[allow(missing_docs)] // documentation missing in model + ThrottlingError(crate::error::ThrottlingError), +} +impl ::std::fmt::Display for CapturePokemonEventsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + CapturePokemonEventsError::InvalidPokeballError(_inner) => _inner.fmt(f), + CapturePokemonEventsError::ThrottlingError(_inner) => _inner.fmt(f), + } + } +} +impl CapturePokemonEventsError { + /// Returns `true` if the error kind is `CapturePokemonEventsError::InvalidPokeballError`. + pub fn is_invalid_pokeball_error(&self) -> bool { + matches!(&self, CapturePokemonEventsError::InvalidPokeballError(_)) + } + /// Returns `true` if the error kind is `CapturePokemonEventsError::ThrottlingError`. + pub fn is_throttling_error(&self) -> bool { + matches!(&self, CapturePokemonEventsError::ThrottlingError(_)) + } + /// Returns the error name string by matching the correct variant. + pub fn name(&self) -> &'static str { + match &self { + CapturePokemonEventsError::InvalidPokeballError(_inner) => _inner.name(), + CapturePokemonEventsError::ThrottlingError(_inner) => _inner.name(), + } + } +} +impl ::std::error::Error for CapturePokemonEventsError { + fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { + match &self { + CapturePokemonEventsError::InvalidPokeballError(_inner) => Some(_inner), + CapturePokemonEventsError::ThrottlingError(_inner) => Some(_inner), + } + } +} +impl ::std::convert::From + for crate::error::CapturePokemonEventsError +{ + fn from( + variant: crate::error::InvalidPokeballError, + ) -> crate::error::CapturePokemonEventsError { + Self::InvalidPokeballError(variant) + } +} +impl ::std::convert::From + for crate::error::CapturePokemonEventsError +{ + fn from(variant: crate::error::ThrottlingError) -> crate::error::CapturePokemonEventsError { + Self::ThrottlingError(variant) + } +} + +/// Error type for the `AttemptCapturingPokemonEvent` operation. +/// Each variant represents an error that can occur for the `AttemptCapturingPokemonEvent` operation. +#[derive(::std::fmt::Debug)] +pub enum AttemptCapturingPokemonEventError { + #[allow(missing_docs)] // documentation missing in model + MasterBallUnsuccessful(crate::error::MasterBallUnsuccessful), +} +impl ::std::fmt::Display for AttemptCapturingPokemonEventError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self { + AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => _inner.fmt(f), + } + } +} +impl AttemptCapturingPokemonEventError { + /// Returns `true` if the error kind is `AttemptCapturingPokemonEventError::MasterBallUnsuccessful`. + pub fn is_master_ball_unsuccessful(&self) -> bool { + matches!( + &self, + AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_) + ) + } + /// Returns the error name string by matching the correct variant. + pub fn name(&self) -> &'static str { + match &self { + AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => _inner.name(), + } + } +} +impl ::std::error::Error for AttemptCapturingPokemonEventError { + fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { + match &self { + AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => Some(_inner), + } + } +} +impl ::std::convert::From + for crate::error::AttemptCapturingPokemonEventError +{ + fn from( + variant: crate::error::MasterBallUnsuccessful, + ) -> crate::error::AttemptCapturingPokemonEventError { + Self::MasterBallUnsuccessful(variant) + } +} + +/// See [`ValidationException`](crate::error::ValidationException). +pub mod validation_exception { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `message` was not provided but it is required when building `ValidationException`. + MissingMessage, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ValidationException`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::error::ValidationException { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`ValidationException`](crate::error::ValidationException). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) message: ::std::option::Option<::std::string::String>, + pub(crate) field_list: + ::std::option::Option<::std::vec::Vec>, + } + impl Builder { + /// A summary of the validation failure. + pub fn message(mut self, input: ::std::string::String) -> Self { + self.message = Some(input); + self + } + /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. + pub fn field_list( + mut self, + input: ::std::option::Option<::std::vec::Vec>, + ) -> Self { + self.field_list = input; + self + } + /// Consumes the builder and constructs a [`ValidationException`](crate::error::ValidationException). + /// + /// The builder fails to construct a [`ValidationException`](crate::error::ValidationException) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::error::ValidationException { + message: self.message.ok_or(ConstraintViolation::MissingMessage)?, + field_list: self.field_list, + }) + } + } +} +/// See [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). +pub mod storage_access_not_authorized { + + impl ::std::convert::From for crate::error::StorageAccessNotAuthorized { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). + pub fn build(self) -> crate::error::StorageAccessNotAuthorized { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::error::StorageAccessNotAuthorized { + crate::error::StorageAccessNotAuthorized {} + } + } +} +/// See [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). +pub mod resource_not_found_exception { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `message` was not provided but it is required when building `ResourceNotFoundException`. + MissingMessage, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ResourceNotFoundException`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::error::ResourceNotFoundException { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) message: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn message(mut self, input: ::std::string::String) -> Self { + self.message = Some(input); + self + } + /// Consumes the builder and constructs a [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). + /// + /// The builder fails to construct a [`ResourceNotFoundException`](crate::error::ResourceNotFoundException) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::error::ResourceNotFoundException { + message: self.message.ok_or(ConstraintViolation::MissingMessage)?, + }) + } + } +} +/// See [`InvalidPokeballError`](crate::error::InvalidPokeballError). +pub mod invalid_pokeball_error { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `pokeball` was not provided but it is required when building `InvalidPokeballError`. + MissingPokeball, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingPokeball => write!(f, "`pokeball` was not provided but it is required when building `InvalidPokeballError`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::error::InvalidPokeballError { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`InvalidPokeballError`](crate::error::InvalidPokeballError). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) pokeball: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn pokeball(mut self, input: ::std::string::String) -> Self { + self.pokeball = Some(input); + self + } + /// Consumes the builder and constructs a [`InvalidPokeballError`](crate::error::InvalidPokeballError). + /// + /// The builder fails to construct a [`InvalidPokeballError`](crate::error::InvalidPokeballError) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::error::InvalidPokeballError { + pokeball: self.pokeball.ok_or(ConstraintViolation::MissingPokeball)?, + }) + } + } +} +/// See [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). +pub mod master_ball_unsuccessful { + + impl ::std::convert::From for crate::error::MasterBallUnsuccessful { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) message: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn message(mut self, input: ::std::option::Option<::std::string::String>) -> Self { + self.message = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_message( + mut self, + input: Option>, + ) -> Self { + self.message = input.map(|v| v.into()); + self + } + /// Consumes the builder and constructs a [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). + pub fn build(self) -> crate::error::MasterBallUnsuccessful { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::error::MasterBallUnsuccessful { + crate::error::MasterBallUnsuccessful { + message: self.message, + } + } + } +} +/// See [`ThrottlingError`](crate::error::ThrottlingError). +pub mod throttling_error { + + impl ::std::convert::From for crate::error::ThrottlingError { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`ThrottlingError`](crate::error::ThrottlingError). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`ThrottlingError`](crate::error::ThrottlingError). + pub fn build(self) -> crate::error::ThrottlingError { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::error::ThrottlingError { + crate::error::ThrottlingError {} + } + } +} +/// See [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). +pub mod unsupported_region_error { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `region` was not provided but it is required when building `UnsupportedRegionError`. + MissingRegion, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingRegion => write!(f, "`region` was not provided but it is required when building `UnsupportedRegionError`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::error::UnsupportedRegionError { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) region: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn region(mut self, input: ::std::string::String) -> Self { + self.region = Some(input); + self + } + /// Consumes the builder and constructs a [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). + /// + /// The builder fails to construct a [`UnsupportedRegionError`](crate::error::UnsupportedRegionError) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::error::UnsupportedRegionError { + region: self.region.ok_or(ConstraintViolation::MissingRegion)?, + }) + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs b/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs new file mode 100644 index 00000000000..3d8b5631a04 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs @@ -0,0 +1,202 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[non_exhaustive] +#[derive(Debug)] +pub struct CapturePokemonEventsErrorMarshaller; + +impl CapturePokemonEventsErrorMarshaller { + pub fn new() -> Self { + CapturePokemonEventsErrorMarshaller + } +} +impl ::aws_smithy_eventstream::frame::MarshallMessage for CapturePokemonEventsErrorMarshaller { + type Input = crate::error::CapturePokemonEventsError; + fn marshall( + &self, + _input: Self::Input, + ) -> std::result::Result< + ::aws_smithy_types::event_stream::Message, + ::aws_smithy_eventstream::error::Error, + > { + let mut headers = Vec::new(); + headers.push(::aws_smithy_types::event_stream::Header::new( + ":message-type", + ::aws_smithy_types::event_stream::HeaderValue::String("exception".into()), + )); + let payload = match _input { + crate::error::CapturePokemonEventsError::InvalidPokeballError(inner) => { + headers.push(::aws_smithy_types::event_stream::Header::new( + ":exception-type", + ::aws_smithy_types::event_stream::HeaderValue::String( + "invalid_pokeball".into(), + ), + )); + headers.push(::aws_smithy_types::event_stream::Header::new( + ":content-type", + ::aws_smithy_types::event_stream::HeaderValue::String( + "application/json".into(), + ), + )); + crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error_error(&inner) + .map_err(|err| ::aws_smithy_eventstream::error::Error::marshalling(format!("{}", err)))? + } + crate::error::CapturePokemonEventsError::ThrottlingError(inner) => { + headers.push(::aws_smithy_types::event_stream::Header::new( + ":exception-type", + ::aws_smithy_types::event_stream::HeaderValue::String("throttlingError".into()), + )); + headers.push(::aws_smithy_types::event_stream::Header::new( + ":content-type", + ::aws_smithy_types::event_stream::HeaderValue::String( + "application/json".into(), + ), + )); + crate::protocol_serde::shape_throttling_error::ser_throttling_error_error(&inner) + .map_err(|err| { + ::aws_smithy_eventstream::error::Error::marshalling(format!("{}", err)) + })? + } + }; + Ok(::aws_smithy_types::event_stream::Message::new_from_parts( + headers, payload, + )) + } +} + +#[non_exhaustive] +#[derive(Debug)] +pub struct CapturePokemonEventsMarshaller; + +impl CapturePokemonEventsMarshaller { + pub fn new() -> Self { + CapturePokemonEventsMarshaller + } +} +impl ::aws_smithy_eventstream::frame::MarshallMessage for CapturePokemonEventsMarshaller { + type Input = crate::model::CapturePokemonEvents; + fn marshall( + &self, + input: Self::Input, + ) -> std::result::Result< + ::aws_smithy_types::event_stream::Message, + ::aws_smithy_eventstream::error::Error, + > { + let mut headers = Vec::new(); + headers.push(::aws_smithy_types::event_stream::Header::new( + ":message-type", + ::aws_smithy_types::event_stream::HeaderValue::String("event".into()), + )); + let payload = match input { + Self::Input::Event(inner) => { + headers.push(::aws_smithy_types::event_stream::Header::new( + ":event-type", + ::aws_smithy_types::event_stream::HeaderValue::String("event".into()), + )); + if let Some(value) = inner.name { + headers.push(::aws_smithy_types::event_stream::Header::new( + "name", + ::aws_smithy_types::event_stream::HeaderValue::String(value.into()), + )); + } + if let Some(value) = inner.captured { + headers.push(::aws_smithy_types::event_stream::Header::new( + "captured", + ::aws_smithy_types::event_stream::HeaderValue::Bool(value), + )); + } + if let Some(value) = inner.shiny { + headers.push(::aws_smithy_types::event_stream::Header::new( + "shiny", + ::aws_smithy_types::event_stream::HeaderValue::Bool(value), + )); + } + headers.push(::aws_smithy_types::event_stream::Header::new( + ":content-type", + ::aws_smithy_types::event_stream::HeaderValue::String( + "application/octet-stream".into(), + ), + )); + if let Some(inner_payload) = inner.pokedex_update { + inner_payload.into_inner() + } else { + Vec::new() + } + } + }; + Ok(::aws_smithy_types::event_stream::Message::new_from_parts( + headers, payload, + )) + } +} + +#[non_exhaustive] +#[derive(Debug)] +pub struct AttemptCapturingPokemonEventUnmarshaller; + +impl AttemptCapturingPokemonEventUnmarshaller { + pub fn new() -> Self { + AttemptCapturingPokemonEventUnmarshaller + } +} +impl ::aws_smithy_eventstream::frame::UnmarshallMessage + for AttemptCapturingPokemonEventUnmarshaller +{ + type Output = crate::model::AttemptCapturingPokemonEvent; + type Error = crate::error::AttemptCapturingPokemonEventError; + fn unmarshall( + &self, + message: &::aws_smithy_types::event_stream::Message, + ) -> std::result::Result< + ::aws_smithy_eventstream::frame::UnmarshalledMessage, + ::aws_smithy_eventstream::error::Error, + > { + let response_headers = ::aws_smithy_eventstream::smithy::parse_response_headers(message)?; + match response_headers.message_type.as_str() { + "event" => match response_headers.smithy_type.as_str() { + "event" => { + let mut builder = crate::model::capturing_event::Builder::default(); + builder = builder.set_payload( + Some( + crate::protocol_serde::shape_capturing_payload::de_capturing_payload_payload(&message.payload()[..]) + .map_err(|err| { + ::aws_smithy_eventstream::error::Error::unmarshalling(format!("failed to unmarshall payload: {}", err)) + })? + ) + ); + Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event( + crate::model::AttemptCapturingPokemonEvent::Event(builder.build()), + )) + } + _unknown_variant => { + return Err(::aws_smithy_eventstream::error::Error::unmarshalling( + format!("unrecognized :event-type: {}", _unknown_variant), + )); + } + }, + "exception" => { + if response_headers.smithy_type.as_str() == "masterball_unsuccessful" { + let mut builder = crate::error::master_ball_unsuccessful::Builder::default(); + builder = crate::protocol_serde::shape_master_ball_unsuccessful::de_master_ball_unsuccessful_json_err(&message.payload()[..], builder) + .map_err(|err| { + ::aws_smithy_eventstream::error::Error::unmarshalling(format!("failed to unmarshall masterball_unsuccessful: {}", err)) + })?; + return Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error( + crate::error::AttemptCapturingPokemonEventError::MasterBallUnsuccessful( + builder.build(), + ), + )); + } + return Err(aws_smithy_eventstream::error::Error::unmarshalling( + format!( + "unrecognized exception: {}", + response_headers.smithy_type.as_str() + ), + )); + } + value => { + return Err(::aws_smithy_eventstream::error::Error::unmarshalling( + format!("unrecognized :message-type: {}", value), + )); + } + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs b/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs new file mode 100644 index 00000000000..a576bb28deb --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs @@ -0,0 +1,27 @@ +// TODO: PATCH - Hyper 1.x compatibility module + +use crate::types::ByteStream; + +// Newtype wrapper to work around orphan rules +#[derive(Debug)] +pub struct HyperIncoming(pub hyper::body::Incoming); + +impl From for ByteStream { + fn from(wrapper: HyperIncoming) -> Self { + ByteStream::from_body_1_x(wrapper.0) + } +} + +impl From for HyperIncoming { + fn from(body: hyper::body::Incoming) -> Self { + HyperIncoming(body) + } +} + +// Provide a blanket implementation for hyper::body::Incoming -> ByteStream +// by going through our newtype +impl From for ByteStream { + fn from(body: hyper::body::Incoming) -> Self { + HyperIncoming::from(body).into() + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/input.rs b/examples/pokemon-service-server-skd-patch/src/input.rs new file mode 100644 index 00000000000..f6d3ba07afe --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/input.rs @@ -0,0 +1,618 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. + +/// A request to access Pokémon storage. +#[derive(::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::hash::Hash)] +pub struct GetStorageInput { + #[allow(missing_docs)] // documentation missing in model + pub user: ::std::string::String, + #[allow(missing_docs)] // documentation missing in model + pub passcode: ::std::string::String, +} +impl GetStorageInput { + #[allow(missing_docs)] // documentation missing in model + pub fn user(&self) -> &str { + use std::ops::Deref; + self.user.deref() + } + #[allow(missing_docs)] // documentation missing in model + pub fn passcode(&self) -> &str { + use std::ops::Deref; + self.passcode.deref() + } +} +impl ::std::fmt::Debug for GetStorageInput { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let mut formatter = f.debug_struct("GetStorageInput"); + formatter.field("user", &"*** Sensitive Data Redacted ***"); + formatter.field("passcode", &"*** Sensitive Data Redacted ***"); + formatter.finish() + } +} +impl GetStorageInput { + /// Creates a new builder-style object to manufacture [`GetStorageInput`](crate::input::GetStorageInput). + pub fn builder() -> crate::input::get_storage_input::Builder { + crate::input::get_storage_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::GetStorageInput { + type Unconstrained = crate::input::get_storage_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct GetPokemonSpeciesInput { + #[allow(missing_docs)] // documentation missing in model + pub name: ::std::string::String, +} +impl GetPokemonSpeciesInput { + #[allow(missing_docs)] // documentation missing in model + pub fn name(&self) -> &str { + use std::ops::Deref; + self.name.deref() + } +} +impl GetPokemonSpeciesInput { + /// Creates a new builder-style object to manufacture [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). + pub fn builder() -> crate::input::get_pokemon_species_input::Builder { + crate::input::get_pokemon_species_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::GetPokemonSpeciesInput { + type Unconstrained = crate::input::get_pokemon_species_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct StreamPokemonRadioInput {} +impl StreamPokemonRadioInput { + /// Creates a new builder-style object to manufacture [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). + pub fn builder() -> crate::input::stream_pokemon_radio_input::Builder { + crate::input::stream_pokemon_radio_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::StreamPokemonRadioInput { + type Unconstrained = crate::input::stream_pokemon_radio_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct CheckHealthInput {} +impl CheckHealthInput { + /// Creates a new builder-style object to manufacture [`CheckHealthInput`](crate::input::CheckHealthInput). + pub fn builder() -> crate::input::check_health_input::Builder { + crate::input::check_health_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::CheckHealthInput { + type Unconstrained = crate::input::check_health_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive(::std::fmt::Debug)] +pub struct CapturePokemonInput { + #[allow(missing_docs)] // documentation missing in model + pub events: ::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + >, + #[allow(missing_docs)] // documentation missing in model + pub region: ::std::string::String, +} +impl CapturePokemonInput { + #[allow(missing_docs)] // documentation missing in model + pub fn events( + &self, + ) -> &::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + > { + &self.events + } + #[allow(missing_docs)] // documentation missing in model + pub fn region(&self) -> &str { + use std::ops::Deref; + self.region.deref() + } +} +impl CapturePokemonInput { + /// Creates a new builder-style object to manufacture [`CapturePokemonInput`](crate::input::CapturePokemonInput). + pub fn builder() -> crate::input::capture_pokemon_input::Builder { + crate::input::capture_pokemon_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::CapturePokemonInput { + type Unconstrained = crate::input::capture_pokemon_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct DoNothingInput {} +impl DoNothingInput { + /// Creates a new builder-style object to manufacture [`DoNothingInput`](crate::input::DoNothingInput). + pub fn builder() -> crate::input::do_nothing_input::Builder { + crate::input::do_nothing_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::DoNothingInput { + type Unconstrained = crate::input::do_nothing_input::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct GetServerStatisticsInput {} +impl GetServerStatisticsInput { + /// Creates a new builder-style object to manufacture [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). + pub fn builder() -> crate::input::get_server_statistics_input::Builder { + crate::input::get_server_statistics_input::Builder::default() + } +} +impl crate::constrained::Constrained for crate::input::GetServerStatisticsInput { + type Unconstrained = crate::input::get_server_statistics_input::Builder; +} +/// See [`GetStorageInput`](crate::input::GetStorageInput). +pub mod get_storage_input { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `user` was not provided but it is required when building `GetStorageInput`. + MissingUser, + /// `passcode` was not provided but it is required when building `GetStorageInput`. + MissingPasscode, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingUser => write!(f, "`user` was not provided but it is required when building `GetStorageInput`"), + ConstraintViolation::MissingPasscode => write!(f, "`passcode` was not provided but it is required when building `GetStorageInput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ConstraintViolation { + pub(crate) fn as_validation_exception_field( + self, + path: ::std::string::String, + ) -> crate::model::ValidationExceptionField { + match self { + ConstraintViolation::MissingUser => crate::model::ValidationExceptionField { + message: format!("Value at '{}/user' failed to satisfy constraint: Member must not be null", path), + path: path + "/user", + }, + ConstraintViolation::MissingPasscode => crate::model::ValidationExceptionField { + message: format!("Value at '{}/passcode' failed to satisfy constraint: Member must not be null", path), + path: path + "/passcode", + }, + } + } + } + impl ::std::convert::From + for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection + { + fn from(constraint_violation: ConstraintViolation) -> Self { + let first_validation_exception_field = + constraint_violation.as_validation_exception_field("".to_owned()); + let validation_exception = crate::error::ValidationException { + message: format!( + "1 validation error detected. {}", + &first_validation_exception_field.message + ), + field_list: Some(vec![first_validation_exception_field]), + }; + Self::ConstraintViolation( + crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) + .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") + ) + } + } + impl ::std::convert::From + for crate::constrained::MaybeConstrained + { + fn from(builder: Builder) -> Self { + Self::Unconstrained(builder) + } + } + impl ::std::convert::TryFrom for crate::input::GetStorageInput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`GetStorageInput`](crate::input::GetStorageInput). + #[derive(::std::clone::Clone, ::std::default::Default)] + pub struct Builder { + pub(crate) user: ::std::option::Option<::std::string::String>, + pub(crate) passcode: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn user(mut self, input: ::std::string::String) -> Self { + self.user = Some(input); + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_user( + mut self, + input: impl ::std::convert::Into<::std::string::String>, + ) -> Self { + self.user = Some(input.into()); + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn passcode(mut self, input: ::std::string::String) -> Self { + self.passcode = Some(input); + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_passcode( + mut self, + input: impl ::std::convert::Into<::std::string::String>, + ) -> Self { + self.passcode = Some(input.into()); + self + } + /// Consumes the builder and constructs a [`GetStorageInput`](crate::input::GetStorageInput). + /// + /// The builder fails to construct a [`GetStorageInput`](crate::input::GetStorageInput) if a [`ConstraintViolation`] occurs. + /// + /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::input::GetStorageInput { + user: self.user.ok_or(ConstraintViolation::MissingUser)?, + passcode: self.passcode.ok_or(ConstraintViolation::MissingPasscode)?, + }) + } + } + impl ::std::fmt::Debug for Builder { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + let mut formatter = f.debug_struct("Builder"); + formatter.field("user", &self.user); + formatter.field("passcode", &self.passcode); + formatter.finish() + } + } +} +/// See [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). +pub mod get_pokemon_species_input { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `name` was not provided but it is required when building `GetPokemonSpeciesInput`. + MissingName, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingName => write!(f, "`name` was not provided but it is required when building `GetPokemonSpeciesInput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ConstraintViolation { + pub(crate) fn as_validation_exception_field( + self, + path: ::std::string::String, + ) -> crate::model::ValidationExceptionField { + match self { + ConstraintViolation::MissingName => crate::model::ValidationExceptionField { + message: format!( + "Value at '{}/name' failed to satisfy constraint: Member must not be null", + path + ), + path: path + "/name", + }, + } + } + } + impl ::std::convert::From + for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection + { + fn from(constraint_violation: ConstraintViolation) -> Self { + let first_validation_exception_field = + constraint_violation.as_validation_exception_field("".to_owned()); + let validation_exception = crate::error::ValidationException { + message: format!( + "1 validation error detected. {}", + &first_validation_exception_field.message + ), + field_list: Some(vec![first_validation_exception_field]), + }; + Self::ConstraintViolation( + crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) + .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") + ) + } + } + impl ::std::convert::From + for crate::constrained::MaybeConstrained + { + fn from(builder: Builder) -> Self { + Self::Unconstrained(builder) + } + } + impl ::std::convert::TryFrom for crate::input::GetPokemonSpeciesInput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) name: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn name(mut self, input: ::std::string::String) -> Self { + self.name = Some(input); + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_name( + mut self, + input: impl ::std::convert::Into<::std::string::String>, + ) -> Self { + self.name = Some(input.into()); + self + } + /// Consumes the builder and constructs a [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). + /// + /// The builder fails to construct a [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::input::GetPokemonSpeciesInput { + name: self.name.ok_or(ConstraintViolation::MissingName)?, + }) + } + } +} +/// See [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). +pub mod stream_pokemon_radio_input { + + impl ::std::convert::From for crate::input::StreamPokemonRadioInput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). + pub fn build(self) -> crate::input::StreamPokemonRadioInput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::input::StreamPokemonRadioInput { + crate::input::StreamPokemonRadioInput {} + } + } +} +/// See [`CheckHealthInput`](crate::input::CheckHealthInput). +pub mod check_health_input { + + impl ::std::convert::From for crate::input::CheckHealthInput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`CheckHealthInput`](crate::input::CheckHealthInput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`CheckHealthInput`](crate::input::CheckHealthInput). + pub fn build(self) -> crate::input::CheckHealthInput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::input::CheckHealthInput { + crate::input::CheckHealthInput {} + } + } +} +/// See [`CapturePokemonInput`](crate::input::CapturePokemonInput). +pub mod capture_pokemon_input { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `events` was not provided but it is required when building `CapturePokemonInput`. + MissingEvents, + /// `region` was not provided but it is required when building `CapturePokemonInput`. + MissingRegion, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingEvents => write!(f, "`events` was not provided but it is required when building `CapturePokemonInput`"), + ConstraintViolation::MissingRegion => write!(f, "`region` was not provided but it is required when building `CapturePokemonInput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ConstraintViolation { + pub(crate) fn as_validation_exception_field( + self, + path: ::std::string::String, + ) -> crate::model::ValidationExceptionField { + match self { + ConstraintViolation::MissingEvents => crate::model::ValidationExceptionField { + message: format!("Value at '{}/events' failed to satisfy constraint: Member must not be null", path), + path: path + "/events", + }, + ConstraintViolation::MissingRegion => crate::model::ValidationExceptionField { + message: format!("Value at '{}/region' failed to satisfy constraint: Member must not be null", path), + path: path + "/region", + }, + } + } + } + impl ::std::convert::From + for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection + { + fn from(constraint_violation: ConstraintViolation) -> Self { + let first_validation_exception_field = + constraint_violation.as_validation_exception_field("".to_owned()); + let validation_exception = crate::error::ValidationException { + message: format!( + "1 validation error detected. {}", + &first_validation_exception_field.message + ), + field_list: Some(vec![first_validation_exception_field]), + }; + Self::ConstraintViolation( + crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) + .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") + ) + } + } + impl ::std::convert::From + for crate::constrained::MaybeConstrained + { + fn from(builder: Builder) -> Self { + Self::Unconstrained(builder) + } + } + impl ::std::convert::TryFrom for crate::input::CapturePokemonInput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`CapturePokemonInput`](crate::input::CapturePokemonInput). + #[derive(::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) events: ::std::option::Option< + ::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + >, + >, + pub(crate) region: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn events( + mut self, + input: ::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + >, + ) -> Self { + self.events = Some(input); + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_events( + mut self, + input: impl ::std::convert::Into< + ::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + >, + >, + ) -> Self { + self.events = Some(input.into()); + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn region(mut self, input: ::std::string::String) -> Self { + self.region = Some(input); + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_region( + mut self, + input: impl ::std::convert::Into<::std::string::String>, + ) -> Self { + self.region = Some(input.into()); + self + } + /// Consumes the builder and constructs a [`CapturePokemonInput`](crate::input::CapturePokemonInput). + /// + /// The builder fails to construct a [`CapturePokemonInput`](crate::input::CapturePokemonInput) if a [`ConstraintViolation`] occurs. + /// + /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::input::CapturePokemonInput { + events: self.events.ok_or(ConstraintViolation::MissingEvents)?, + region: self.region.ok_or(ConstraintViolation::MissingRegion)?, + }) + } + } +} +/// See [`DoNothingInput`](crate::input::DoNothingInput). +pub mod do_nothing_input { + + impl ::std::convert::From for crate::input::DoNothingInput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`DoNothingInput`](crate::input::DoNothingInput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`DoNothingInput`](crate::input::DoNothingInput). + pub fn build(self) -> crate::input::DoNothingInput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::input::DoNothingInput { + crate::input::DoNothingInput {} + } + } +} +/// See [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). +pub mod get_server_statistics_input { + + impl ::std::convert::From for crate::input::GetServerStatisticsInput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). + pub fn build(self) -> crate::input::GetServerStatisticsInput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::input::GetServerStatisticsInput { + crate::input::GetServerStatisticsInput {} + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/lib.rs b/examples/pokemon-service-server-skd-patch/src/lib.rs new file mode 100644 index 00000000000..f3899ee3083 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/lib.rs @@ -0,0 +1,317 @@ +#![allow(deprecated)] +#![allow(unknown_lints)] +#![allow(clippy::module_inception)] +#![allow(clippy::upper_case_acronyms)] +#![allow(clippy::large_enum_variant)] +#![allow(clippy::wrong_self_convention)] +#![allow(clippy::should_implement_trait)] +#![allow(clippy::disallowed_names)] +#![allow(clippy::vec_init_then_push)] +#![allow(clippy::type_complexity)] +#![allow(clippy::needless_return)] +#![allow(clippy::derive_partial_eq_without_eq)] +#![allow(clippy::result_large_err)] +#![allow(clippy::unnecessary_map_on_constructor)] +#![allow(clippy::deprecated_semver)] +#![allow(rustdoc::bare_urls)] +#![allow(rustdoc::redundant_explicit_links)] +#![allow(rustdoc::invalid_html_tags)] +#![forbid(unsafe_code)] +#![cfg_attr(docsrs, feature(doc_cfg))] +//! The Pokémon Service allows you to retrieve information about Pokémon species. + +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +//! A fast and customizable Rust implementation of the PokemonService Smithy service. +//! +//! # Using PokemonService +//! +//! The primary entrypoint is [`PokemonService`]: it satisfies the [`Service`](::tower::Service) +//! trait and therefore can be handed to a [`hyper` server](https://github.com/hyperium/hyper) via [`PokemonService::into_make_service`] +//! or used in AWS Lambda +#![cfg_attr( + feature = "aws-lambda", + doc = " via [`LambdaHandler`](crate::server::routing::LambdaHandler)." +)] +#![cfg_attr( + not(feature = "aws-lambda"), + doc = " by enabling the `aws-lambda` feature flag and utilizing the `LambdaHandler`." +)] +//! The [`crate::input`], [`crate::output`], and [`crate::error`] +//! modules provide the types used in each operation. +//! +//! ### Running on Hyper +//! +//! ```rust,no_run +//! # use std::net::SocketAddr; +//! # async fn dummy() { +//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; +//! +//! # let app = PokemonService::builder( +//! # PokemonServiceConfig::builder() +//! # .build() +//! # ).build_unchecked(); +//! use hyper_util::rt::TokioIo; +//! use hyper_util::service::TowerToHyperService; +//! use ::tokio::net::TcpListener; +//! use ::tower::Service; +//! +//! let app = app.into_make_service(); +//! let bind: SocketAddr = "127.0.0.1:6969".parse() +//! .expect("unable to parse the server bind address and port"); +//! let listener = TcpListener::bind(bind).await.expect("failed to bind"); +//! +//! loop { +//! let (stream, remote_addr) = listener.accept().await.expect("failed to accept connection"); +//! let io = TokioIo::new(stream); +//! let mut app = app.clone(); +//! +//! ::tokio::task::spawn(async move { +//! let service = app.call(remote_addr).await.expect("failed to create service"); +//! let hyper_service = TowerToHyperService::new(service); +//! +//! if let Err(err) = ::hyper::server::conn::http1::Builder::new() +//! .serve_connection(io, hyper_service) +//! .await +//! { +//! eprintln!("Error serving connection: {:?}", err); +//! } +//! }); +//! } +//! # } +//! ``` +//! +//! ### Running on Lambda +//! +//! ```rust,ignore +//! use pokemon_service_server_sdk::server::routing::LambdaHandler; +//! use pokemon_service_server_sdk::PokemonService; +//! +//! # async fn dummy() { +//! # let app = PokemonService::builder( +//! # PokemonServiceConfig::builder() +//! # .build() +//! # ).build_unchecked(); +//! let handler = LambdaHandler::new(app); +//! lambda_http::run(handler).await.unwrap(); +//! # } +//! ``` +//! +//! # Building the PokemonService +//! +//! To construct [`PokemonService`] we use [`PokemonServiceBuilder`] returned by [`PokemonService::builder`]. +//! +//! ## Plugins +//! +//! The [`PokemonService::builder`] method, returning [`PokemonServiceBuilder`], +//! accepts a config object on which plugins can be registered. +//! Plugins allow you to build middleware which is aware of the operation it is being applied to. +//! +//! ```rust,no_run +//! # use pokemon_service_server_sdk::server::plugin::IdentityPlugin as LoggingPlugin; +//! # use pokemon_service_server_sdk::server::plugin::IdentityPlugin as MetricsPlugin; +//! use pokemon_service_server_sdk::server::body::BoxBody; +//! use pokemon_service_server_sdk::server::plugin::HttpPlugins; +//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; +//! +//! let http_plugins = HttpPlugins::new() +//! .push(LoggingPlugin) +//! .push(MetricsPlugin); +//! let config = PokemonServiceConfig::builder().http_plugin(http_plugins).build(); +//! let _app = PokemonService::builder::(config).build_unchecked(); +//! ``` +//! +//! Check out [`crate::server::plugin`] to learn more about plugins. +//! +//! ## Handlers +//! +//! [`PokemonServiceBuilder`] provides a setter method for each operation in your Smithy model. The setter methods expect an async function as input, matching the signature for the corresponding operation in your Smithy model. +//! We call these async functions **handlers**. This is where your application business logic lives. +//! +//! Every handler must take an `Input`, and optional [`extractor arguments`](crate::server::request), while returning: +//! +//! * A `Result` if your operation has modeled errors, or +//! * An `Output` otherwise. +//! +//! ```rust,no_run +//! # struct Input; +//! # struct Output; +//! # struct Error; +//! async fn infallible_handler(input: Input) -> Output { todo!() } +//! +//! async fn fallible_handler(input: Input) -> Result { todo!() } +//! ``` +//! +//! Handlers can accept up to 8 extractors: +//! +//! ```rust,no_run +//! # struct Input; +//! # struct Output; +//! # struct Error; +//! # struct State; +//! # use std::net::SocketAddr; +//! use pokemon_service_server_sdk::server::request::{extension::Extension, connect_info::ConnectInfo}; +//! +//! async fn handler_with_no_extensions(input: Input) -> Output { +//! todo!() +//! } +//! +//! async fn handler_with_one_extractor(input: Input, ext: Extension) -> Output { +//! todo!() +//! } +//! +//! async fn handler_with_two_extractors( +//! input: Input, +//! ext0: Extension, +//! ext1: ConnectInfo, +//! ) -> Output { +//! todo!() +//! } +//! ``` +//! +//! See the [`operation module`](crate::operation) for information on precisely what constitutes a handler. +//! +//! ## Build +//! +//! You can convert [`PokemonServiceBuilder`] into [`PokemonService`] using either [`PokemonServiceBuilder::build`] or [`PokemonServiceBuilder::build_unchecked`]. +//! +//! [`PokemonServiceBuilder::build`] requires you to provide a handler for every single operation in your Smithy model. It will return an error if that is not the case. +//! +//! [`PokemonServiceBuilder::build_unchecked`], instead, does not require exhaustiveness. The server will automatically return 500 Internal Server Error to all requests for operations that do not have a registered handler. +//! [`PokemonServiceBuilder::build_unchecked`] is particularly useful if you are deploying your Smithy service as a collection of Lambda functions, where each Lambda is only responsible for a subset of the operations in the Smithy service (or even a single one!). +//! +//! # Example +//! +//! ```rust,no_run +//! # use std::net::SocketAddr; +//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; +//! +//! #[::tokio::main] +//! pub async fn main() { +//! let config = PokemonServiceConfig::builder().build(); +//! let app = PokemonService::builder(config) +//! .capture_pokemon(capture_pokemon) +//! .check_health(check_health) +//! .do_nothing(do_nothing) +//! .get_pokemon_species(get_pokemon_species) +//! .get_server_statistics(get_server_statistics) +//! .get_storage(get_storage) +//! .stream_pokemon_radio(stream_pokemon_radio) +//! .build() +//! .expect("failed to build an instance of PokemonService"); +//! +//! use hyper_util::rt::TokioIo; +//! use hyper_util::service::TowerToHyperService; +//! use ::tokio::net::TcpListener; +//! use ::tower::Service; +//! +//! let app = app.into_make_service(); +//! let bind: SocketAddr = "127.0.0.1:6969".parse() +//! .expect("unable to parse the server bind address and port"); +//! let listener = TcpListener::bind(bind).await.expect("failed to bind"); +//! +//! loop { +//! let (stream, remote_addr) = listener.accept().await.expect("failed to accept connection"); +//! let io = TokioIo::new(stream); +//! let mut app = app.clone(); +//! +//! ::tokio::task::spawn(async move { +//! let service = app.call(remote_addr).await.expect("failed to create service"); +//! let hyper_service = TowerToHyperService::new(service); +//! +//! if let Err(err) = ::hyper::server::conn::http1::Builder::new() +//! .serve_connection(io, hyper_service) +//! .await +//! { +//! eprintln!("Error serving connection: {:?}", err); +//! } +//! }); +//! } +//! } +//! +//! use pokemon_service_server_sdk::{input, output, error}; +//! +//! async fn capture_pokemon(input: input::CapturePokemonInput) -> Result { +//! todo!() +//! } +//! +//! async fn check_health(input: input::CheckHealthInput) -> output::CheckHealthOutput { +//! todo!() +//! } +//! +//! async fn do_nothing(input: input::DoNothingInput) -> output::DoNothingOutput { +//! todo!() +//! } +//! +//! async fn get_pokemon_species(input: input::GetPokemonSpeciesInput) -> Result { +//! todo!() +//! } +//! +//! async fn get_server_statistics(input: input::GetServerStatisticsInput) -> output::GetServerStatisticsOutput { +//! todo!() +//! } +//! +//! async fn get_storage(input: input::GetStorageInput) -> Result { +//! todo!() +//! } +//! +//! async fn stream_pokemon_radio(input: input::StreamPokemonRadioInput) -> output::StreamPokemonRadioOutput { +//! todo!() +//! } +//! +//! ``` +//! +//! [`serve`]: https://docs.rs/hyper/0.14.16/hyper/server/struct.Builder.html#method.serve +//! [`tower::make::MakeService`]: https://docs.rs/tower/latest/tower/make/trait.MakeService.html +//! [HTTP binding traits]: https://smithy.io/2.0/spec/http-bindings.html +//! [operations]: https://smithy.io/2.0/spec/service-types.html#operation +//! [hyper server]: https://docs.rs/hyper/latest/hyper/server/index.html +//! [Service]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html +pub use crate::service::{ + MissingOperationsError, PokemonService, PokemonServiceBuilder, PokemonServiceConfig, + PokemonServiceConfigBuilder, +}; + +/// Contains the types that are re-exported from the `aws-smithy-http-server` crate. +pub mod server { + // Re-export all types from the `aws-smithy-http-server` crate. + pub use ::aws_smithy_http_server::*; +} + +/// Crate version number. +pub static PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// All error types that operations can return. Documentation on these types is copied from the model. +pub mod error; + +/// Input structures for operations. Documentation on these types is copied from the model. +pub mod input; + +/// Data structures used by operation inputs/outputs. Documentation on these types is copied from the model. +pub mod model; + +/// All operations that this crate can perform. +pub mod operation; + +/// A collection of types representing each operation defined in the service closure. +/// +/// The [plugin system](::aws_smithy_http_server::plugin) makes use of these +/// [zero-sized types](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts) (ZSTs) to +/// parameterize [`Plugin`](::aws_smithy_http_server::plugin::Plugin) implementations. Their traits, such as +/// [`OperationShape`](::aws_smithy_http_server::operation::OperationShape), can be used to provide +/// operation specific information to the [`Layer`](::tower::Layer) being applied. +pub mod operation_shape; + +/// Output structures for operations. Documentation on these types is copied from the model. +pub mod output; + +mod service; + +/// Data primitives referenced by other data types. +pub mod types; + +/// Constrained types for constrained shapes. +mod constrained; + +mod event_stream_serde; + +pub(crate) mod protocol_serde; diff --git a/examples/pokemon-service-server-skd-patch/src/model.rs b/examples/pokemon-service-server-skd-patch/src/model.rs new file mode 100644 index 00000000000..3a3ae63e89b --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/model.rs @@ -0,0 +1,578 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. + +/// Describes one specific validation failure for an input member. +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct ValidationExceptionField { + /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. + pub path: ::std::string::String, + /// A detailed description of the validation failure. + pub message: ::std::string::String, +} +impl ValidationExceptionField { + /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. + pub fn path(&self) -> &str { + use std::ops::Deref; + self.path.deref() + } + /// A detailed description of the validation failure. + pub fn message(&self) -> &str { + use std::ops::Deref; + self.message.deref() + } +} +impl ValidationExceptionField { + /// Creates a new builder-style object to manufacture [`ValidationExceptionField`](crate::model::ValidationExceptionField). + pub fn builder() -> crate::model::validation_exception_field::Builder { + crate::model::validation_exception_field::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct FlavorText { + /// The localized flavor text for an API resource in a specific language. + pub flavor_text: ::std::string::String, + /// The language this name is in. + pub language: crate::model::Language, +} +impl FlavorText { + /// The localized flavor text for an API resource in a specific language. + pub fn flavor_text(&self) -> &str { + use std::ops::Deref; + self.flavor_text.deref() + } + /// The language this name is in. + pub fn language(&self) -> &crate::model::Language { + &self.language + } +} +impl FlavorText { + /// Creates a new builder-style object to manufacture [`FlavorText`](crate::model::FlavorText). + pub fn builder() -> crate::model::flavor_text::Builder { + crate::model::flavor_text::Builder::default() + } +} + +/// Supported languages for FlavorText entries. +#[derive( + ::std::clone::Clone, + ::std::cmp::Eq, + ::std::cmp::Ord, + ::std::cmp::PartialEq, + ::std::cmp::PartialOrd, + ::std::fmt::Debug, + ::std::hash::Hash, +)] +pub enum Language { + /// American English. + English, + /// Español. + Spanish, + /// Italiano. + Italian, + /// 日本語。 + Japanese, +} +/// See [`Language`](crate::model::Language). +pub mod language { + #[derive(Debug, PartialEq)] + pub struct ConstraintViolation(pub(crate) ::std::string::String); + + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + r#"Value provided for 'com.aws.example#Language' failed to satisfy constraint: Member must satisfy enum value set: [en, es, it, jp]"# + ) + } + } + + impl ::std::error::Error for ConstraintViolation {} +} +impl ::std::convert::TryFrom<&str> for Language { + type Error = crate::model::language::ConstraintViolation; + fn try_from( + s: &str, + ) -> ::std::result::Result>::Error> { + match s { + "en" => Ok(Language::English), + "es" => Ok(Language::Spanish), + "it" => Ok(Language::Italian), + "jp" => Ok(Language::Japanese), + _ => Err(crate::model::language::ConstraintViolation(s.to_owned())), + } + } +} +impl ::std::convert::TryFrom<::std::string::String> for Language { + type Error = crate::model::language::ConstraintViolation; + fn try_from( + s: ::std::string::String, + ) -> ::std::result::Result>::Error> + { + s.as_str().try_into() + } +} +impl std::str::FromStr for Language { + type Err = crate::model::language::ConstraintViolation; + fn from_str(s: &str) -> std::result::Result::Err> { + Self::try_from(s) + } +} +impl Language { + /// Returns the `&str` value of the enum member. + pub fn as_str(&self) -> &str { + match self { + Language::English => "en", + Language::Spanish => "es", + Language::Italian => "it", + Language::Japanese => "jp", + } + } + /// Returns all the `&str` representations of the enum members. + pub const fn values() -> &'static [&'static str] { + &["en", "es", "it", "jp"] + } +} +impl ::std::convert::AsRef for Language { + fn as_ref(&self) -> &str { + self.as_str() + } +} +impl crate::constrained::Constrained for Language { + type Unconstrained = ::std::string::String; +} + +impl ::std::convert::From<::std::string::String> + for crate::constrained::MaybeConstrained +{ + fn from(value: ::std::string::String) -> Self { + Self::Unconstrained(value) + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)] +pub enum CapturePokemonEvents { + #[allow(missing_docs)] // documentation missing in model + Event(crate::model::CaptureEvent), +} +impl CapturePokemonEvents { + #[allow(irrefutable_let_patterns)] + /// Tries to convert the enum instance into [`Event`](crate::model::CapturePokemonEvents::Event), extracting the inner [`CaptureEvent`](crate::model::CaptureEvent). + /// Returns `Err(&Self)` if it can't be converted. + pub fn as_event(&self) -> ::std::result::Result<&crate::model::CaptureEvent, &Self> { + if let CapturePokemonEvents::Event(val) = &self { + ::std::result::Result::Ok(val) + } else { + ::std::result::Result::Err(self) + } + } + /// Returns true if this is a [`Event`](crate::model::CapturePokemonEvents::Event). + pub fn is_event(&self) -> bool { + self.as_event().is_ok() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct CaptureEvent { + #[allow(missing_docs)] // documentation missing in model + pub name: ::std::option::Option<::std::string::String>, + #[allow(missing_docs)] // documentation missing in model + pub captured: ::std::option::Option, + #[allow(missing_docs)] // documentation missing in model + pub shiny: ::std::option::Option, + #[allow(missing_docs)] // documentation missing in model + pub pokedex_update: ::std::option::Option<::aws_smithy_types::Blob>, +} +impl CaptureEvent { + #[allow(missing_docs)] // documentation missing in model + pub fn name(&self) -> ::std::option::Option<&str> { + self.name.as_deref() + } + #[allow(missing_docs)] // documentation missing in model + pub fn captured(&self) -> ::std::option::Option { + self.captured + } + #[allow(missing_docs)] // documentation missing in model + pub fn shiny(&self) -> ::std::option::Option { + self.shiny + } + #[allow(missing_docs)] // documentation missing in model + pub fn pokedex_update(&self) -> ::std::option::Option<&::aws_smithy_types::Blob> { + self.pokedex_update.as_ref() + } +} +impl CaptureEvent { + /// Creates a new builder-style object to manufacture [`CaptureEvent`](crate::model::CaptureEvent). + pub fn builder() -> crate::model::capture_event::Builder { + crate::model::capture_event::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)] +pub enum AttemptCapturingPokemonEvent { + #[allow(missing_docs)] // documentation missing in model + Event(crate::model::CapturingEvent), +} +impl AttemptCapturingPokemonEvent { + #[allow(irrefutable_let_patterns)] + /// Tries to convert the enum instance into [`Event`](crate::model::AttemptCapturingPokemonEvent::Event), extracting the inner [`CapturingEvent`](crate::model::CapturingEvent). + /// Returns `Err(&Self)` if it can't be converted. + pub fn as_event(&self) -> ::std::result::Result<&crate::model::CapturingEvent, &Self> { + if let AttemptCapturingPokemonEvent::Event(val) = &self { + ::std::result::Result::Ok(val) + } else { + ::std::result::Result::Err(self) + } + } + /// Returns true if this is a [`Event`](crate::model::AttemptCapturingPokemonEvent::Event). + pub fn is_event(&self) -> bool { + self.as_event().is_ok() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct CapturingEvent { + #[allow(missing_docs)] // documentation missing in model + pub payload: ::std::option::Option, +} +impl CapturingEvent { + #[allow(missing_docs)] // documentation missing in model + pub fn payload(&self) -> ::std::option::Option<&crate::model::CapturingPayload> { + self.payload.as_ref() + } +} +impl CapturingEvent { + /// Creates a new builder-style object to manufacture [`CapturingEvent`](crate::model::CapturingEvent). + pub fn builder() -> crate::model::capturing_event::Builder { + crate::model::capturing_event::Builder::default() + } +} +impl crate::constrained::Constrained for crate::model::CapturingEvent { + type Unconstrained = crate::model::capturing_event::Builder; +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct CapturingPayload { + #[allow(missing_docs)] // documentation missing in model + pub name: ::std::option::Option<::std::string::String>, + #[allow(missing_docs)] // documentation missing in model + pub pokeball: ::std::option::Option<::std::string::String>, +} +impl CapturingPayload { + #[allow(missing_docs)] // documentation missing in model + pub fn name(&self) -> ::std::option::Option<&str> { + self.name.as_deref() + } + #[allow(missing_docs)] // documentation missing in model + pub fn pokeball(&self) -> ::std::option::Option<&str> { + self.pokeball.as_deref() + } +} +impl CapturingPayload { + /// Creates a new builder-style object to manufacture [`CapturingPayload`](crate::model::CapturingPayload). + pub fn builder() -> crate::model::capturing_payload::Builder { + crate::model::capturing_payload::Builder::default() + } +} +impl crate::constrained::Constrained for crate::model::CapturingPayload { + type Unconstrained = crate::model::capturing_payload::Builder; +} +/// See [`ValidationExceptionField`](crate::model::ValidationExceptionField). +pub mod validation_exception_field { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `path` was not provided but it is required when building `ValidationExceptionField`. + MissingPath, + /// `message` was not provided but it is required when building `ValidationExceptionField`. + MissingMessage, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingPath => write!(f, "`path` was not provided but it is required when building `ValidationExceptionField`"), + ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ValidationExceptionField`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::model::ValidationExceptionField { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`ValidationExceptionField`](crate::model::ValidationExceptionField). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) path: ::std::option::Option<::std::string::String>, + pub(crate) message: ::std::option::Option<::std::string::String>, + } + impl Builder { + /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. + pub fn path(mut self, input: ::std::string::String) -> Self { + self.path = Some(input); + self + } + /// A detailed description of the validation failure. + pub fn message(mut self, input: ::std::string::String) -> Self { + self.message = Some(input); + self + } + /// Consumes the builder and constructs a [`ValidationExceptionField`](crate::model::ValidationExceptionField). + /// + /// The builder fails to construct a [`ValidationExceptionField`](crate::model::ValidationExceptionField) if a [`ConstraintViolation`] occurs. + /// + /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::model::ValidationExceptionField { + path: self.path.ok_or(ConstraintViolation::MissingPath)?, + message: self.message.ok_or(ConstraintViolation::MissingMessage)?, + }) + } + } +} +/// See [`FlavorText`](crate::model::FlavorText). +pub mod flavor_text { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `flavor_text` was not provided but it is required when building `FlavorText`. + MissingFlavorText, + /// `language` was not provided but it is required when building `FlavorText`. + MissingLanguage, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingFlavorText => write!( + f, + "`flavor_text` was not provided but it is required when building `FlavorText`" + ), + ConstraintViolation::MissingLanguage => write!( + f, + "`language` was not provided but it is required when building `FlavorText`" + ), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::model::FlavorText { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`FlavorText`](crate::model::FlavorText). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) flavor_text: ::std::option::Option<::std::string::String>, + pub(crate) language: ::std::option::Option, + } + impl Builder { + /// The localized flavor text for an API resource in a specific language. + pub fn flavor_text(mut self, input: ::std::string::String) -> Self { + self.flavor_text = Some(input); + self + } + /// The language this name is in. + pub fn language(mut self, input: crate::model::Language) -> Self { + self.language = Some(input); + self + } + /// Consumes the builder and constructs a [`FlavorText`](crate::model::FlavorText). + /// + /// The builder fails to construct a [`FlavorText`](crate::model::FlavorText) if a [`ConstraintViolation`] occurs. + /// + /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::model::FlavorText { + flavor_text: self + .flavor_text + .ok_or(ConstraintViolation::MissingFlavorText)?, + language: self.language.ok_or(ConstraintViolation::MissingLanguage)?, + }) + } + } +} +/// See [`CaptureEvent`](crate::model::CaptureEvent). +pub mod capture_event { + + impl ::std::convert::From for crate::model::CaptureEvent { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`CaptureEvent`](crate::model::CaptureEvent). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) name: ::std::option::Option<::std::string::String>, + pub(crate) captured: ::std::option::Option, + pub(crate) shiny: ::std::option::Option, + pub(crate) pokedex_update: ::std::option::Option<::aws_smithy_types::Blob>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn name(mut self, input: ::std::option::Option<::std::string::String>) -> Self { + self.name = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn captured(mut self, input: ::std::option::Option) -> Self { + self.captured = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn shiny(mut self, input: ::std::option::Option) -> Self { + self.shiny = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn pokedex_update( + mut self, + input: ::std::option::Option<::aws_smithy_types::Blob>, + ) -> Self { + self.pokedex_update = input; + self + } + /// Consumes the builder and constructs a [`CaptureEvent`](crate::model::CaptureEvent). + pub fn build(self) -> crate::model::CaptureEvent { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::model::CaptureEvent { + crate::model::CaptureEvent { + name: self.name, + captured: self.captured, + shiny: self.shiny, + pokedex_update: self.pokedex_update, + } + } + } +} +/// See [`CapturingEvent`](crate::model::CapturingEvent). +pub mod capturing_event { + + impl ::std::convert::From for crate::model::CapturingEvent { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`CapturingEvent`](crate::model::CapturingEvent). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) payload: ::std::option::Option, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn payload( + mut self, + input: ::std::option::Option, + ) -> Self { + self.payload = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_payload( + mut self, + input: Option>, + ) -> Self { + self.payload = input.map(|v| v.into()); + self + } + /// Consumes the builder and constructs a [`CapturingEvent`](crate::model::CapturingEvent). + pub fn build(self) -> crate::model::CapturingEvent { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::model::CapturingEvent { + crate::model::CapturingEvent { + payload: self.payload, + } + } + } +} +/// See [`CapturingPayload`](crate::model::CapturingPayload). +pub mod capturing_payload { + + impl ::std::convert::From for crate::model::CapturingPayload { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`CapturingPayload`](crate::model::CapturingPayload). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) name: ::std::option::Option<::std::string::String>, + pub(crate) pokeball: ::std::option::Option<::std::string::String>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn name(mut self, input: ::std::option::Option<::std::string::String>) -> Self { + self.name = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_name( + mut self, + input: Option>, + ) -> Self { + self.name = input.map(|v| v.into()); + self + } + #[allow(missing_docs)] // documentation missing in model + pub fn pokeball(mut self, input: ::std::option::Option<::std::string::String>) -> Self { + self.pokeball = input; + self + } + #[allow(missing_docs)] // documentation missing in model + pub(crate) fn set_pokeball( + mut self, + input: Option>, + ) -> Self { + self.pokeball = input.map(|v| v.into()); + self + } + /// Consumes the builder and constructs a [`CapturingPayload`](crate::model::CapturingPayload). + pub fn build(self) -> crate::model::CapturingPayload { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::model::CapturingPayload { + crate::model::CapturingPayload { + name: self.name, + pokeball: self.pokeball, + } + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/operation.rs b/examples/pokemon-service-server-skd-patch/src/operation.rs new file mode 100644 index 00000000000..5fe1e67bbeb --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/operation.rs @@ -0,0 +1,639 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +const CONTENT_TYPE_GETSTORAGE: ::mime::Mime = ::mime::APPLICATION_JSON; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`GetStorageInput`](crate::input::GetStorageInput) using modelled bindings. + pub struct GetStorageInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for GetStorageInputFuture { + type Output = Result< + crate::input::GetStorageInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::GetStorageInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = GetStorageInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_GETSTORAGE, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_get_storage::de_get_storage_http_request(request).await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + GetStorageInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::GetStorageOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_get_storage::ser_get_storage_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::error::GetStorageError +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_get_storage::ser_get_storage_http_error(&self) { + Ok(mut response) => { + response.extensions_mut().insert( + ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), + ); + response + } + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +const CONTENT_TYPE_GETPOKEMONSPECIES: ::mime::Mime = ::mime::APPLICATION_JSON; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput) using modelled bindings. + pub struct GetPokemonSpeciesInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for GetPokemonSpeciesInputFuture { + type Output = Result< + crate::input::GetPokemonSpeciesInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::GetPokemonSpeciesInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = GetPokemonSpeciesInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_GETPOKEMONSPECIES, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_get_pokemon_species::de_get_pokemon_species_http_request( + request, + ) + .await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + GetPokemonSpeciesInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::GetPokemonSpeciesOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_get_pokemon_species::ser_get_pokemon_species_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::error::GetPokemonSpeciesError +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_get_pokemon_species::ser_get_pokemon_species_http_error( + &self, + ) { + Ok(mut response) => { + response.extensions_mut().insert( + ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), + ); + response + } + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +const CONTENT_TYPE_STREAMPOKEMONRADIO: ::mime::Mime = ::mime::APPLICATION_OCTET_STREAM; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput) using modelled bindings. + pub struct StreamPokemonRadioInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for StreamPokemonRadioInputFuture { + type Output = Result< + crate::input::StreamPokemonRadioInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::StreamPokemonRadioInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = StreamPokemonRadioInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_STREAMPOKEMONRADIO, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_stream_pokemon_radio::de_stream_pokemon_radio_http_request( + request, + ) + .await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + StreamPokemonRadioInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::StreamPokemonRadioOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_stream_pokemon_radio::ser_stream_pokemon_radio_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +const CONTENT_TYPE_CHECKHEALTH: ::mime::Mime = ::mime::APPLICATION_JSON; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`CheckHealthInput`](crate::input::CheckHealthInput) using modelled bindings. + pub struct CheckHealthInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for CheckHealthInputFuture { + type Output = Result< + crate::input::CheckHealthInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::CheckHealthInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = CheckHealthInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_CHECKHEALTH, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_check_health::de_check_health_http_request(request).await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + CheckHealthInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::CheckHealthOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_check_health::ser_check_health_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +static CONTENT_TYPE_CAPTUREPOKEMON: std::sync::LazyLock<::mime::Mime> = + std::sync::LazyLock::new(|| { + "application/vnd.amazon.eventstream" + .parse::<::mime::Mime>() + .expect("BUG: MIME parsing failed, content_type is not valid") + }); +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`CapturePokemonInput`](crate::input::CapturePokemonInput) using modelled bindings. + pub struct CapturePokemonInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for CapturePokemonInputFuture { + type Output = Result< + crate::input::CapturePokemonInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::CapturePokemonInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + // TODO: PATCH - Changed from Into to http-body 1.x constraint for hyper 1.x compatibility + // This supports any body type that implements http-body 1.x (including custom body types) + B: http_body_1_0::Body + Send + Sync + 'static, + B::Error: Into<::aws_smithy_types::body::Error> + 'static, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = CapturePokemonInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_CAPTUREPOKEMON, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_capture_pokemon::de_capture_pokemon_http_request(request) + .await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + CapturePokemonInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::CapturePokemonOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_capture_pokemon::ser_capture_pokemon_http_response(self) + { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::error::CapturePokemonError +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_capture_pokemon::ser_capture_pokemon_http_error(&self) { + Ok(mut response) => { + response.extensions_mut().insert( + ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), + ); + response + } + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +const CONTENT_TYPE_DONOTHING: ::mime::Mime = ::mime::APPLICATION_JSON; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`DoNothingInput`](crate::input::DoNothingInput) using modelled bindings. + pub struct DoNothingInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for DoNothingInputFuture { + type Output = Result< + crate::input::DoNothingInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::DoNothingInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = DoNothingInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_DONOTHING, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_do_nothing::de_do_nothing_http_request(request).await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + DoNothingInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::DoNothingOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_do_nothing::ser_do_nothing_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} + +const CONTENT_TYPE_GETSERVERSTATISTICS: ::mime::Mime = ::mime::APPLICATION_JSON; +::pin_project_lite::pin_project! { + /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the + /// [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput) using modelled bindings. + pub struct GetServerStatisticsInputFuture { + inner: std::pin::Pin> + Send>> + } +} + +impl std::future::Future for GetServerStatisticsInputFuture { + type Output = Result< + crate::input::GetServerStatisticsInput, + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, + >; + + fn poll( + self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + let this = self.project(); + this.inner.as_mut().poll(cx) + } +} + +impl + ::aws_smithy_http_server::request::FromRequest< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + B, + > for crate::input::GetServerStatisticsInput +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B: 'static, + + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; + type Future = GetServerStatisticsInputFuture; + + fn from_request(request: ::http::Request) -> Self::Future { + let fut = async move { + if !::aws_smithy_http_server::protocol::accept_header_classifier( + request.headers(), + &CONTENT_TYPE_GETSERVERSTATISTICS, + ) { + return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); + } + crate::protocol_serde::shape_get_server_statistics::de_get_server_statistics_http_request(request) + .await + }; + use ::futures_util::future::TryFutureExt; + let fut = fut.map_err( + |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { + ::tracing::debug!(error = %e, "failed to deserialize request"); + ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( + e, + ) + }, + ); + GetServerStatisticsInputFuture { + inner: Box::pin(fut), + } + } +} +impl + ::aws_smithy_http_server::response::IntoResponse< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + > for crate::output::GetServerStatisticsOutput +{ + fn into_response(self) -> ::aws_smithy_http_server::response::Response { + match crate::protocol_serde::shape_get_server_statistics::ser_get_server_statistics_http_response(self) { + Ok(response) => response, + Err(e) => { + ::tracing::error!(error = %e, "failed to serialize response"); + ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) + } + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/operation_shape.rs b/examples/pokemon-service-server-skd-patch/src/operation_shape.rs new file mode 100644 index 00000000000..1f5b0455292 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/operation_shape.rs @@ -0,0 +1,289 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. + +/// Retrieve information about your Pokédex. +pub struct GetStorage; + +impl ::aws_smithy_http_server::operation::OperationShape for GetStorage { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetStorage", + "com.aws.example", + "GetStorage", + ); + + type Input = crate::input::GetStorageInput; + type Output = crate::output::GetStorageOutput; + type Error = crate::error::GetStorageError; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetStorage { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::sensitivity::headers::MakeHeaders< + fn( + &::http::header::HeaderName, + ) + -> ::aws_smithy_http_server::instrumentation::sensitivity::headers::HeaderMarker, + >, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeLabel< + fn(usize) -> bool, + >, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + .header({ + |name: &::http::header::HeaderName| { + let name_match = matches!(name.as_str(), "passcode"); + let key_suffix = None; + let value = name_match; + ::aws_smithy_http_server::instrumentation::sensitivity::headers::HeaderMarker { + key_suffix, + value, + } + } + } as fn(&_) -> _) + .label( + { |index: usize| matches!(index, 1) } as fn(usize) -> bool, + None, + ) + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// Retrieve information about a Pokémon species. +pub struct GetPokemonSpecies; + +impl ::aws_smithy_http_server::operation::OperationShape for GetPokemonSpecies { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetPokemonSpecies", + "com.aws.example", + "GetPokemonSpecies", + ); + + type Input = crate::input::GetPokemonSpeciesInput; + type Output = crate::output::GetPokemonSpeciesOutput; + type Error = crate::error::GetPokemonSpeciesError; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetPokemonSpecies { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// Fetch a radio song from the database and stream it back as a playable audio. +pub struct StreamPokemonRadio; + +impl ::aws_smithy_http_server::operation::OperationShape for StreamPokemonRadio { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#StreamPokemonRadio", + "com.aws.example", + "StreamPokemonRadio", + ); + + type Input = crate::input::StreamPokemonRadioInput; + type Output = crate::output::StreamPokemonRadioOutput; + type Error = std::convert::Infallible; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for StreamPokemonRadio { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// Health check operation, to check the service is up Not yet a deep check +pub struct CheckHealth; + +impl ::aws_smithy_http_server::operation::OperationShape for CheckHealth { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#CheckHealth", + "com.aws.example", + "CheckHealth", + ); + + type Input = crate::input::CheckHealthInput; + type Output = crate::output::CheckHealthOutput; + type Error = std::convert::Infallible; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for CheckHealth { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// Capture Pokémons via event streams. +pub struct CapturePokemon; + +impl ::aws_smithy_http_server::operation::OperationShape for CapturePokemon { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#CapturePokemon", + "com.aws.example", + "CapturePokemon", + ); + + type Input = crate::input::CapturePokemonInput; + type Output = crate::output::CapturePokemonOutput; + type Error = crate::error::CapturePokemonError; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for CapturePokemon { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// DoNothing operation, used to stress test the framework. +pub struct DoNothing; + +impl ::aws_smithy_http_server::operation::OperationShape for DoNothing { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#DoNothing", + "com.aws.example", + "DoNothing", + ); + + type Input = crate::input::DoNothingInput; + type Output = crate::output::DoNothingOutput; + type Error = std::convert::Infallible; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for DoNothing { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} + +/// Retrieve HTTP server statistiscs, such as calls count. +pub struct GetServerStatistics; + +impl ::aws_smithy_http_server::operation::OperationShape for GetServerStatistics { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetServerStatistics", + "com.aws.example", + "GetServerStatistics", + ); + + type Input = crate::input::GetServerStatisticsInput; + type Output = crate::output::GetServerStatisticsOutput; + type Error = std::convert::Infallible; +} + +impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetServerStatistics { + type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >, + >; + type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< + ::aws_smithy_http_server::instrumentation::MakeIdentity, + ::aws_smithy_http_server::instrumentation::MakeIdentity, + >; + + fn request_fmt() -> Self::RequestFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() + } + + fn response_fmt() -> Self::ResponseFmt { + ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/output.rs b/examples/pokemon-service-server-skd-patch/src/output.rs new file mode 100644 index 00000000000..c45ad71a145 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/output.rs @@ -0,0 +1,461 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. + +/// Contents of the Pokémon storage. +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct GetStorageOutput { + /// A list of Pokémon species. + pub collection: ::std::vec::Vec<::std::string::String>, +} +impl GetStorageOutput { + /// A list of Pokémon species. + pub fn collection(&self) -> &[::std::string::String] { + use std::ops::Deref; + self.collection.deref() + } +} +impl GetStorageOutput { + /// Creates a new builder-style object to manufacture [`GetStorageOutput`](crate::output::GetStorageOutput). + pub fn builder() -> crate::output::get_storage_output::Builder { + crate::output::get_storage_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct GetPokemonSpeciesOutput { + /// The name for this resource. + pub name: ::std::string::String, + /// A list of flavor text entries for this Pokémon species. + pub flavor_text_entries: ::std::vec::Vec, +} +impl GetPokemonSpeciesOutput { + /// The name for this resource. + pub fn name(&self) -> &str { + use std::ops::Deref; + self.name.deref() + } + /// A list of flavor text entries for this Pokémon species. + pub fn flavor_text_entries(&self) -> &[crate::model::FlavorText] { + use std::ops::Deref; + self.flavor_text_entries.deref() + } +} +impl GetPokemonSpeciesOutput { + /// Creates a new builder-style object to manufacture [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). + pub fn builder() -> crate::output::get_pokemon_species_output::Builder { + crate::output::get_pokemon_species_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive(::std::fmt::Debug)] +pub struct StreamPokemonRadioOutput { + #[allow(missing_docs)] // documentation missing in model + pub data: ::aws_smithy_types::byte_stream::ByteStream, +} +impl StreamPokemonRadioOutput { + #[allow(missing_docs)] // documentation missing in model + pub fn data(&self) -> &::aws_smithy_types::byte_stream::ByteStream { + &self.data + } +} +impl StreamPokemonRadioOutput { + /// Creates a new builder-style object to manufacture [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). + pub fn builder() -> crate::output::stream_pokemon_radio_output::Builder { + crate::output::stream_pokemon_radio_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct CheckHealthOutput {} +impl CheckHealthOutput { + /// Creates a new builder-style object to manufacture [`CheckHealthOutput`](crate::output::CheckHealthOutput). + pub fn builder() -> crate::output::check_health_output::Builder { + crate::output::check_health_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive(::std::fmt::Debug)] +pub struct CapturePokemonOutput { + #[allow(missing_docs)] // documentation missing in model + pub events: ::aws_smithy_http::event_stream::EventStreamSender< + crate::model::CapturePokemonEvents, + crate::error::CapturePokemonEventsError, + >, +} +impl CapturePokemonOutput { + #[allow(missing_docs)] // documentation missing in model + pub fn events( + &self, + ) -> &::aws_smithy_http::event_stream::EventStreamSender< + crate::model::CapturePokemonEvents, + crate::error::CapturePokemonEventsError, + > { + &self.events + } +} +impl CapturePokemonOutput { + /// Creates a new builder-style object to manufacture [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). + pub fn builder() -> crate::output::capture_pokemon_output::Builder { + crate::output::capture_pokemon_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct DoNothingOutput {} +impl DoNothingOutput { + /// Creates a new builder-style object to manufacture [`DoNothingOutput`](crate::output::DoNothingOutput). + pub fn builder() -> crate::output::do_nothing_output::Builder { + crate::output::do_nothing_output::Builder::default() + } +} + +#[allow(missing_docs)] // documentation missing in model +#[derive( + ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, +)] +pub struct GetServerStatisticsOutput { + /// The number of calls executed by the server. + pub calls_count: i64, +} +impl GetServerStatisticsOutput { + /// The number of calls executed by the server. + pub fn calls_count(&self) -> i64 { + self.calls_count + } +} +impl GetServerStatisticsOutput { + /// Creates a new builder-style object to manufacture [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). + pub fn builder() -> crate::output::get_server_statistics_output::Builder { + crate::output::get_server_statistics_output::Builder::default() + } +} +/// See [`GetStorageOutput`](crate::output::GetStorageOutput). +pub mod get_storage_output { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `collection` was not provided but it is required when building `GetStorageOutput`. + MissingCollection, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingCollection => write!(f, "`collection` was not provided but it is required when building `GetStorageOutput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::output::GetStorageOutput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`GetStorageOutput`](crate::output::GetStorageOutput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) collection: ::std::option::Option<::std::vec::Vec<::std::string::String>>, + } + impl Builder { + /// A list of Pokémon species. + pub fn collection(mut self, input: ::std::vec::Vec<::std::string::String>) -> Self { + self.collection = Some(input); + self + } + /// Consumes the builder and constructs a [`GetStorageOutput`](crate::output::GetStorageOutput). + /// + /// The builder fails to construct a [`GetStorageOutput`](crate::output::GetStorageOutput) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::output::GetStorageOutput { + collection: self + .collection + .ok_or(ConstraintViolation::MissingCollection)?, + }) + } + } +} +/// See [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). +pub mod get_pokemon_species_output { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `name` was not provided but it is required when building `GetPokemonSpeciesOutput`. + MissingName, + /// `flavor_text_entries` was not provided but it is required when building `GetPokemonSpeciesOutput`. + MissingFlavorTextEntries, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingName => write!(f, "`name` was not provided but it is required when building `GetPokemonSpeciesOutput`"), + ConstraintViolation::MissingFlavorTextEntries => write!(f, "`flavor_text_entries` was not provided but it is required when building `GetPokemonSpeciesOutput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::output::GetPokemonSpeciesOutput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) name: ::std::option::Option<::std::string::String>, + pub(crate) flavor_text_entries: + ::std::option::Option<::std::vec::Vec>, + } + impl Builder { + /// The name for this resource. + pub fn name(mut self, input: ::std::string::String) -> Self { + self.name = Some(input); + self + } + /// A list of flavor text entries for this Pokémon species. + pub fn flavor_text_entries( + mut self, + input: ::std::vec::Vec, + ) -> Self { + self.flavor_text_entries = Some(input); + self + } + /// Consumes the builder and constructs a [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). + /// + /// The builder fails to construct a [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput) if a [`ConstraintViolation`] occurs. + /// + /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::output::GetPokemonSpeciesOutput { + name: self.name.ok_or(ConstraintViolation::MissingName)?, + flavor_text_entries: self + .flavor_text_entries + .ok_or(ConstraintViolation::MissingFlavorTextEntries)?, + }) + } + } +} +/// See [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). +pub mod stream_pokemon_radio_output { + + impl ::std::convert::From for crate::output::StreamPokemonRadioOutput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). + #[derive(::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) data: ::std::option::Option<::aws_smithy_types::byte_stream::ByteStream>, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn data(mut self, input: ::aws_smithy_types::byte_stream::ByteStream) -> Self { + self.data = Some(input); + self + } + /// Consumes the builder and constructs a [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). + pub fn build(self) -> crate::output::StreamPokemonRadioOutput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::output::StreamPokemonRadioOutput { + crate::output::StreamPokemonRadioOutput { + data: self.data.unwrap_or_default(), + } + } + } +} +/// See [`CheckHealthOutput`](crate::output::CheckHealthOutput). +pub mod check_health_output { + + impl ::std::convert::From for crate::output::CheckHealthOutput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`CheckHealthOutput`](crate::output::CheckHealthOutput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`CheckHealthOutput`](crate::output::CheckHealthOutput). + pub fn build(self) -> crate::output::CheckHealthOutput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::output::CheckHealthOutput { + crate::output::CheckHealthOutput {} + } + } +} +/// See [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). +pub mod capture_pokemon_output { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `events` was not provided but it is required when building `CapturePokemonOutput`. + MissingEvents, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingEvents => write!(f, "`events` was not provided but it is required when building `CapturePokemonOutput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::output::CapturePokemonOutput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). + #[derive(::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) events: ::std::option::Option< + ::aws_smithy_http::event_stream::EventStreamSender< + crate::model::CapturePokemonEvents, + crate::error::CapturePokemonEventsError, + >, + >, + } + impl Builder { + #[allow(missing_docs)] // documentation missing in model + pub fn events( + mut self, + input: ::aws_smithy_http::event_stream::EventStreamSender< + crate::model::CapturePokemonEvents, + crate::error::CapturePokemonEventsError, + >, + ) -> Self { + self.events = Some(input); + self + } + /// Consumes the builder and constructs a [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). + /// + /// The builder fails to construct a [`CapturePokemonOutput`](crate::output::CapturePokemonOutput) if a [`ConstraintViolation`] occurs. + /// + pub fn build(self) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::output::CapturePokemonOutput { + events: self.events.ok_or(ConstraintViolation::MissingEvents)?, + }) + } + } +} +/// See [`DoNothingOutput`](crate::output::DoNothingOutput). +pub mod do_nothing_output { + + impl ::std::convert::From for crate::output::DoNothingOutput { + fn from(builder: Builder) -> Self { + builder.build() + } + } + /// A builder for [`DoNothingOutput`](crate::output::DoNothingOutput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder {} + impl Builder { + /// Consumes the builder and constructs a [`DoNothingOutput`](crate::output::DoNothingOutput). + pub fn build(self) -> crate::output::DoNothingOutput { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints(self) -> crate::output::DoNothingOutput { + crate::output::DoNothingOutput {} + } + } +} +/// See [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). +pub mod get_server_statistics_output { + + #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] + /// Holds one variant for each of the ways the builder can fail. + #[non_exhaustive] + #[allow(clippy::enum_variant_names)] + pub enum ConstraintViolation { + /// `calls_count` was not provided but it is required when building `GetServerStatisticsOutput`. + MissingCallsCount, + } + impl ::std::fmt::Display for ConstraintViolation { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ConstraintViolation::MissingCallsCount => write!(f, "`calls_count` was not provided but it is required when building `GetServerStatisticsOutput`"), + } + } + } + impl ::std::error::Error for ConstraintViolation {} + impl ::std::convert::TryFrom for crate::output::GetServerStatisticsOutput { + type Error = ConstraintViolation; + + fn try_from(builder: Builder) -> ::std::result::Result { + builder.build() + } + } + /// A builder for [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). + #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] + pub struct Builder { + pub(crate) calls_count: ::std::option::Option, + } + impl Builder { + /// The number of calls executed by the server. + pub fn calls_count(mut self, input: i64) -> Self { + self.calls_count = Some(input); + self + } + /// Consumes the builder and constructs a [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). + /// + /// The builder fails to construct a [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput) if a [`ConstraintViolation`] occurs. + /// + pub fn build( + self, + ) -> Result { + self.build_enforcing_all_constraints() + } + fn build_enforcing_all_constraints( + self, + ) -> Result { + Ok(crate::output::GetServerStatisticsOutput { + calls_count: self + .calls_count + .ok_or(ConstraintViolation::MissingCallsCount)?, + }) + } + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs new file mode 100644 index 00000000000..7b5ea4e8e63 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs @@ -0,0 +1,58 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub(crate) mod shape_capture_pokemon; + +pub(crate) mod shape_check_health; + +pub(crate) mod shape_do_nothing; + +pub(crate) mod shape_get_pokemon_species; + +pub(crate) mod shape_get_server_statistics; + +pub(crate) mod shape_get_storage; + +pub(crate) mod shape_stream_pokemon_radio; + +pub(crate) mod shape_capture_pokemon_input; + +pub(crate) mod shape_do_nothing_output; + +pub(crate) mod shape_get_pokemon_species_input; + +pub(crate) mod shape_get_pokemon_species_output; + +pub(crate) mod shape_get_server_statistics_output; + +pub(crate) mod shape_get_storage_input; + +pub(crate) mod shape_get_storage_output; + +pub(crate) mod shape_invalid_pokeball_error; + +pub(crate) mod shape_master_ball_unsuccessful; + +pub(crate) mod shape_resource_not_found_exception; + +pub(crate) mod shape_storage_access_not_authorized; + +pub(crate) mod shape_stream_pokemon_radio_output; + +pub(crate) mod shape_throttling_error; + +pub(crate) mod shape_unsupported_region_error; + +pub(crate) mod shape_validation_exception; + +pub(crate) fn or_empty_doc(data: &[u8]) -> &[u8] { + if data.is_empty() { + b"{}" + } else { + data + } +} + +pub(crate) mod shape_capturing_payload; + +pub(crate) mod shape_flavor_text; + +pub(crate) mod shape_validation_exception_field; diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs new file mode 100644 index 00000000000..1598292bf7e --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs @@ -0,0 +1,226 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_capture_pokemon_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::CapturePokemonInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + // TODO: PATCH - Changed from Into to http-body 1.x constraint for hyper 1.x compatibility + B: http_body_1_0::Body + Send + Sync + 'static, + B::Error: Into<::aws_smithy_types::body::Error> + 'static, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::capture_pokemon_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + if let Some(value) = { + Some( + crate::protocol_serde::shape_capture_pokemon_input::de_events_payload( + // TODO: PATCH - Use from_body_1_x for hyper 1.x compatibility instead of body.into() + // This works with any http-body 1.x compatible body type + &mut ::aws_smithy_types::byte_stream::ByteStream::from_body_1_x(body).into_inner(), + )?, + ) + } { + input = input.set_events(value) + } + let input_string = uri.path(); + let (input_string, (_, m1)) = + ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>( + "capture-pokemon-event", + ), + ), + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::bytes::complete::take_until("/"), + ::nom::combinator::rest, + )), + ), + ))(input_string)?; + debug_assert_eq!("", input_string); + input = + input.set_region(crate::protocol_serde::shape_capture_pokemon_input::de_region(m1)?); + input.build()? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_capture_pokemon_http_response( + #[allow(unused_variables)] output: crate::output::CapturePokemonOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let body = + ::aws_smithy_http_server::body::boxed(::aws_smithy_http_server::body::wrap_stream({ + let error_marshaller = + crate::event_stream_serde::CapturePokemonEventsErrorMarshaller::new(); + let marshaller = crate::event_stream_serde::CapturePokemonEventsMarshaller::new(); + let signer = ::aws_smithy_eventstream::frame::NoOpSigner {}; + let adapter: ::aws_smithy_http::event_stream::MessageStreamAdapter<_, _> = output + .events + .into_body_stream(marshaller, error_marshaller, signer); + adapter + })); + builder.body(body)? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_capture_pokemon_http_error( + error: &crate::error::CapturePokemonError, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + match error { + crate::error::CapturePokemonError::UnsupportedRegionError(output) => { + let payload = crate::protocol_serde::shape_unsupported_region_error::ser_unsupported_region_error_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "UnsupportedRegionError", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(500) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::CapturePokemonError::ThrottlingError(output) => { + let payload = + crate::protocol_serde::shape_throttling_error::ser_throttling_error_error( + output, + )?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ThrottlingError", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(400) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::CapturePokemonError::ValidationException(output) => { + let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ValidationException", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(400) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::CapturePokemonError::MasterBallUnsuccessful(output) => { + let payload = crate::protocol_serde::shape_master_ball_unsuccessful::ser_master_ball_unsuccessful_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "MasterBallUnsuccessful", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(500) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::CapturePokemonError::InvalidPokeballError(output) => { + let payload = crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/vnd.amazon.eventstream", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "InvalidPokeballError", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(400) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + } + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs new file mode 100644 index 00000000000..3f101c29dc0 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs @@ -0,0 +1,29 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn de_events_payload( + body: &mut ::aws_smithy_types::body::SdkBody, +) -> std::result::Result< + ::aws_smithy_http::event_stream::Receiver< + crate::model::AttemptCapturingPokemonEvent, + crate::error::AttemptCapturingPokemonEventError, + >, + ::aws_smithy_json::deserialize::error::DeserializeError, +> { + let unmarshaller = crate::event_stream_serde::AttemptCapturingPokemonEventUnmarshaller::new(); + let body = std::mem::replace(body, ::aws_smithy_types::body::SdkBody::taken()); + Ok(::aws_smithy_http::event_stream::Receiver::new( + unmarshaller, + body, + )) +} + +pub fn de_region( + value: &str, +) -> std::result::Result< + ::std::string::String, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> { + let value = ::percent_encoding::percent_decode_str(value) + .decode_utf8()? + .into_owned(); + Ok(value) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs new file mode 100644 index 00000000000..a44b5503102 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs @@ -0,0 +1,90 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub(crate) fn de_capturing_payload_payload( + input: &[u8], +) -> ::std::result::Result< + crate::model::CapturingPayload, + ::aws_smithy_json::deserialize::error::DeserializeError, +> { + let mut tokens_owned = + ::aws_smithy_json::deserialize::json_token_iter(crate::protocol_serde::or_empty_doc(input)) + .peekable(); + let tokens = &mut tokens_owned; + let result = crate::protocol_serde::shape_capturing_payload::de_capturing_payload(tokens)? + .ok_or_else(|| { + ::aws_smithy_json::deserialize::error::DeserializeError::custom( + "expected payload member value", + ) + }); + if tokens.next().is_some() { + return Err( + ::aws_smithy_json::deserialize::error::DeserializeError::custom( + "found more JSON tokens after completing parsing", + ), + ); + } + result +} + +pub(crate) fn de_capturing_payload<'a, I>( + tokens: &mut ::std::iter::Peekable, +) -> ::std::result::Result< + Option, + ::aws_smithy_json::deserialize::error::DeserializeError, +> +where + I: Iterator< + Item = Result< + ::aws_smithy_json::deserialize::Token<'a>, + ::aws_smithy_json::deserialize::error::DeserializeError, + >, + >, +{ + match tokens.next().transpose()? { + Some(::aws_smithy_json::deserialize::Token::ValueNull { .. }) => Ok(None), + Some(::aws_smithy_json::deserialize::Token::StartObject { .. }) => { + #[allow(unused_mut)] + let mut builder = crate::model::capturing_payload::Builder::default(); + loop { + match tokens.next().transpose()? { + Some(::aws_smithy_json::deserialize::Token::EndObject { .. }) => break, + Some(::aws_smithy_json::deserialize::Token::ObjectKey { key, .. }) => { + match key.to_unescaped()?.as_ref() { + "name" => { + builder = builder.set_name( + ::aws_smithy_json::deserialize::token::expect_string_or_null( + tokens.next(), + )? + .map(|s| s.to_unescaped().map(|u| u.into_owned())) + .transpose()?, + ); + } + "pokeball" => { + builder = builder.set_pokeball( + ::aws_smithy_json::deserialize::token::expect_string_or_null( + tokens.next(), + )? + .map(|s| s.to_unescaped().map(|u| u.into_owned())) + .transpose()?, + ); + } + _ => ::aws_smithy_json::deserialize::token::skip_value(tokens)?, + } + } + other => { + return Err( + ::aws_smithy_json::deserialize::error::DeserializeError::custom( + format!("expected object key or end object, found: {:?}", other), + ), + ) + } + } + } + Ok(Some(builder.build())) + } + _ => Err( + ::aws_smithy_json::deserialize::error::DeserializeError::custom( + "expected start object or null", + ), + ), + } +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs new file mode 100644 index 00000000000..fd673922b0b --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs @@ -0,0 +1,54 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_check_health_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::CheckHealthInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::check_health_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + ::aws_smithy_http_server::protocol::content_type_header_classifier_smithy(&headers, None)?; + input.build() + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_check_health_http_response( + #[allow(unused_variables)] output: crate::output::CheckHealthOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let payload = ""; + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + let body = ::aws_smithy_http_server::body::to_boxed(payload); + builder.body(body)? + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs new file mode 100644 index 00000000000..067bdd12265 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs @@ -0,0 +1,56 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_do_nothing_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::DoNothingInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::do_nothing_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + input.build() + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_do_nothing_http_response( + #[allow(unused_variables)] output: crate::output::DoNothingOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let payload = + crate::protocol_serde::shape_do_nothing_output::ser_do_nothing_output_output_output( + &output, + )?; + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + let body = ::aws_smithy_http_server::body::to_boxed(payload); + builder.body(body)? + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs new file mode 100644 index 00000000000..f3a00378542 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs @@ -0,0 +1,20 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_do_nothing_output_output_output( + value: &crate::output::DoNothingOutput, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_do_nothing_output::ser_do_nothing_output_output( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_do_nothing_output_output( + #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + #[allow(unused_variables)] input: &crate::output::DoNothingOutput, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs new file mode 100644 index 00000000000..c955b79fc6e --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs @@ -0,0 +1,13 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_flavor_text( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::model::FlavorText, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("flavorText").string(input.flavor_text.as_str()); + } + { + object.key("language").string(input.language.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs new file mode 100644 index 00000000000..77cfa3624da --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs @@ -0,0 +1,136 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_get_pokemon_species_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::GetPokemonSpeciesInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::get_pokemon_species_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + let input_string = uri.path(); + let (input_string, (_, m1)) = + ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>( + "pokemon-species", + ), + ), + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::bytes::complete::take_until("/"), + ::nom::combinator::rest, + )), + ), + ))(input_string)?; + debug_assert_eq!("", input_string); + input = + input.set_name(crate::protocol_serde::shape_get_pokemon_species_input::de_name(m1)?); + input.build()? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_get_pokemon_species_http_response( + #[allow(unused_variables)] output: crate::output::GetPokemonSpeciesOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let payload = + crate::protocol_serde::shape_get_pokemon_species_output::ser_get_pokemon_species_output_output_output(&output)? + ; + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + let body = ::aws_smithy_http_server::body::to_boxed(payload); + builder.body(body)? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_get_pokemon_species_http_error( + error: &crate::error::GetPokemonSpeciesError, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + match error { + crate::error::GetPokemonSpeciesError::ResourceNotFoundException(output) => { + let payload = crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ResourceNotFoundException", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(404) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::GetPokemonSpeciesError::ValidationException(output) => { + let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ValidationException", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(400) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + } + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs new file mode 100644 index 00000000000..21f97a054fc --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs @@ -0,0 +1,12 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn de_name( + value: &str, +) -> std::result::Result< + ::std::string::String, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> { + let value = ::percent_encoding::percent_decode_str(value) + .decode_utf8()? + .into_owned(); + Ok(value) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs new file mode 100644 index 00000000000..a6ace50f850 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs @@ -0,0 +1,35 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_get_pokemon_species_output_output_output( + value: &crate::output::GetPokemonSpeciesOutput, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_get_pokemon_species_output::ser_get_pokemon_species_output_output( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_get_pokemon_species_output_output( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::output::GetPokemonSpeciesOutput, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + let mut array_1 = object.key("flavorTextEntries").start_array(); + for item_2 in &input.flavor_text_entries { + { + #[allow(unused_mut)] + let mut object_3 = array_1.value().start_object(); + crate::protocol_serde::shape_flavor_text::ser_flavor_text(&mut object_3, item_2)?; + object_3.finish(); + } + } + array_1.finish(); + } + { + object.key("name").string(input.name.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs new file mode 100644 index 00000000000..80e934069ff --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs @@ -0,0 +1,55 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_get_server_statistics_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::GetServerStatisticsInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::get_server_statistics_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + input.build() + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_get_server_statistics_http_response( + #[allow(unused_variables)] output: crate::output::GetServerStatisticsOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let payload = + crate::protocol_serde::shape_get_server_statistics_output::ser_get_server_statistics_output_output_output(&output)? + ; + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + let body = ::aws_smithy_http_server::body::to_boxed(payload); + builder.body(body)? + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs new file mode 100644 index 00000000000..00f4abc0aeb --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs @@ -0,0 +1,23 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_get_server_statistics_output_output_output( + value: &crate::output::GetServerStatisticsOutput, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_get_server_statistics_output::ser_get_server_statistics_output_output(&mut object, value)?; + object.finish(); + Ok(out) +} + +pub fn ser_get_server_statistics_output_output( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::output::GetServerStatisticsOutput, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("calls_count").number( + #[allow(clippy::useless_conversion)] + ::aws_smithy_types::Number::NegInt((input.calls_count).into()), + ); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs new file mode 100644 index 00000000000..0bb6dc748db --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs @@ -0,0 +1,163 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_get_storage_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::GetStorageInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::get_storage_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + if let Some(value) = + crate::protocol_serde::shape_get_storage_input::de_passcode_header(&headers)? + { + input = input.set_passcode(value) + } + let input_string = uri.path(); + let (input_string, (_, m1)) = + ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>("pokedex"), + ), + ::nom::sequence::preceded( + ::nom::bytes::complete::tag("/"), + ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( + ::nom::bytes::complete::take_until("/"), + ::nom::combinator::rest, + )), + ), + ))(input_string)?; + debug_assert_eq!("", input_string); + input = input.set_user(crate::protocol_serde::shape_get_storage_input::de_user(m1)?); + input.build()? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_get_storage_http_response( + #[allow(unused_variables)] output: crate::output::GetStorageOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let payload = + crate::protocol_serde::shape_get_storage_output::ser_get_storage_output_output_output( + &output, + )?; + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + let body = ::aws_smithy_http_server::body::to_boxed(payload); + builder.body(body)? + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_get_storage_http_error( + error: &crate::error::GetStorageError, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + match error { + crate::error::GetStorageError::ResourceNotFoundException(output) => { + let payload = crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ResourceNotFoundException", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(404) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::GetStorageError::StorageAccessNotAuthorized(output) => { + let payload = crate::protocol_serde::shape_storage_access_not_authorized::ser_storage_access_not_authorized_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "StorageAccessNotAuthorized", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(401) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + crate::error::GetStorageError::ValidationException(output) => { + let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/json", + ); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::HeaderName::from_static("x-amzn-errortype"), + "ValidationException", + ); + let content_length = payload.len(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_LENGTH, + content_length, + ); + builder + .status(400) + .body(::aws_smithy_http_server::body::to_boxed(payload))? + } + } + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs new file mode 100644 index 00000000000..17f5204cf80 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs @@ -0,0 +1,22 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub(crate) fn de_passcode_header( + header_map: &::aws_smithy_runtime_api::http::Headers, +) -> ::std::result::Result< + ::std::option::Option<::std::string::String>, + ::aws_smithy_http::header::ParseError, +> { + let headers = header_map.get_all("passcode"); + ::aws_smithy_http::header::one_or_none(headers) +} + +pub fn de_user( + value: &str, +) -> std::result::Result< + ::std::string::String, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> { + let value = ::percent_encoding::percent_decode_str(value) + .decode_utf8()? + .into_owned(); + Ok(value) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs new file mode 100644 index 00000000000..9c8160fce19 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs @@ -0,0 +1,29 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_get_storage_output_output_output( + value: &crate::output::GetStorageOutput, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_get_storage_output::ser_get_storage_output_output( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_get_storage_output_output( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::output::GetStorageOutput, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + let mut array_1 = object.key("collection").start_array(); + for item_2 in &input.collection { + { + array_1.value().string(item_2.as_str()); + } + } + array_1.finish(); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs new file mode 100644 index 00000000000..06e3bfdac80 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs @@ -0,0 +1,23 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_invalid_pokeball_error_error( + value: &crate::error::InvalidPokeballError, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_invalid_pokeball_error( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::error::InvalidPokeballError, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("pokeball").string(input.pokeball.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs new file mode 100644 index 00000000000..8edf08a0e1a --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs @@ -0,0 +1,72 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_master_ball_unsuccessful_error( + value: &crate::error::MasterBallUnsuccessful, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_master_ball_unsuccessful::ser_master_ball_unsuccessful( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_master_ball_unsuccessful( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::error::MasterBallUnsuccessful, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + if let Some(var_1) = &input.message { + object.key("message").string(var_1.as_str()); + } + Ok(()) +} + +pub(crate) fn de_master_ball_unsuccessful_json_err( + value: &[u8], + mut builder: crate::error::master_ball_unsuccessful::Builder, +) -> ::std::result::Result< + crate::error::master_ball_unsuccessful::Builder, + ::aws_smithy_json::deserialize::error::DeserializeError, +> { + let mut tokens_owned = + ::aws_smithy_json::deserialize::json_token_iter(crate::protocol_serde::or_empty_doc(value)) + .peekable(); + let tokens = &mut tokens_owned; + ::aws_smithy_json::deserialize::token::expect_start_object(tokens.next())?; + loop { + match tokens.next().transpose()? { + Some(::aws_smithy_json::deserialize::Token::EndObject { .. }) => break, + Some(::aws_smithy_json::deserialize::Token::ObjectKey { key, .. }) => { + match key.to_unescaped()?.as_ref() { + "message" => { + builder = builder.set_message( + ::aws_smithy_json::deserialize::token::expect_string_or_null( + tokens.next(), + )? + .map(|s| s.to_unescaped().map(|u| u.into_owned())) + .transpose()?, + ); + } + _ => ::aws_smithy_json::deserialize::token::skip_value(tokens)?, + } + } + other => { + return Err( + ::aws_smithy_json::deserialize::error::DeserializeError::custom(format!( + "expected object key or end object, found: {:?}", + other + )), + ) + } + } + } + if tokens.next().is_some() { + return Err( + ::aws_smithy_json::deserialize::error::DeserializeError::custom( + "found more JSON tokens after completing parsing", + ), + ); + } + Ok(builder) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs new file mode 100644 index 00000000000..34b63fe69c7 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs @@ -0,0 +1,23 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_resource_not_found_exception_error( + value: &crate::error::ResourceNotFoundException, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_resource_not_found_exception( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::error::ResourceNotFoundException, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("message").string(input.message.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs new file mode 100644 index 00000000000..8572989d52e --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs @@ -0,0 +1,20 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_storage_access_not_authorized_error( + value: &crate::error::StorageAccessNotAuthorized, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_storage_access_not_authorized::ser_storage_access_not_authorized( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_storage_access_not_authorized( + #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + #[allow(unused_variables)] input: &crate::error::StorageAccessNotAuthorized, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs new file mode 100644 index 00000000000..1e7c0ff13cb --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs @@ -0,0 +1,51 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +#[allow(clippy::unnecessary_wraps)] +pub async fn de_stream_pokemon_radio_http_request( + #[allow(unused_variables)] request: ::http::Request, +) -> std::result::Result< + crate::input::StreamPokemonRadioInput, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, +> +where + B: ::aws_smithy_http_server::body::HttpBody + Send, + B::Data: Send, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: + From<::Error>, +{ + Ok({ + #[allow(unused_mut)] + let mut input = crate::input::stream_pokemon_radio_input::Builder::default(); + #[allow(unused_variables)] + let ::aws_smithy_runtime_api::http::RequestParts { + uri, headers, body, .. + } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); + ::aws_smithy_http_server::protocol::content_type_header_classifier_smithy(&headers, None)?; + input.build() + }) +} + +#[allow(clippy::unnecessary_wraps)] +pub fn ser_stream_pokemon_radio_http_response( + #[allow(unused_variables)] output: crate::output::StreamPokemonRadioOutput, +) -> std::result::Result< + ::aws_smithy_http_server::response::Response, + ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, +> { + Ok({ + #[allow(unused_mut)] + let mut builder = ::http::Response::builder(); + builder = ::aws_smithy_http::header::set_response_header_if_absent( + builder, + ::http::header::CONTENT_TYPE, + "application/octet-stream", + ); + let http_status: u16 = 200; + builder = builder.status(http_status); + let body = ::aws_smithy_http_server::body::boxed(::aws_smithy_http_server::body::wrap_stream( + ::aws_smithy_http::futures_stream_adapter::FuturesStreamCompatByteStream::new( + crate::protocol_serde::shape_stream_pokemon_radio_output::ser_data_http_payload( output.data)? + ) + )); + builder.body(body)? + }) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs new file mode 100644 index 00000000000..55587893101 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs @@ -0,0 +1,9 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_data_http_payload( + payload: ::aws_smithy_types::byte_stream::ByteStream, +) -> ::std::result::Result< + ::aws_smithy_types::byte_stream::ByteStream, + ::aws_smithy_types::error::operation::BuildError, +> { + Ok(payload) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs new file mode 100644 index 00000000000..b254155c2a3 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs @@ -0,0 +1,17 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_throttling_error_error( + value: &crate::error::ThrottlingError, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_throttling_error::ser_throttling_error(&mut object, value)?; + object.finish(); + Ok(out) +} + +pub fn ser_throttling_error( + #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + #[allow(unused_variables)] input: &crate::error::ThrottlingError, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs new file mode 100644 index 00000000000..50fe15cc003 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs @@ -0,0 +1,23 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_unsupported_region_error_error( + value: &crate::error::UnsupportedRegionError, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_unsupported_region_error::ser_unsupported_region_error( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_unsupported_region_error( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::error::UnsupportedRegionError, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("region").string(input.region.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs new file mode 100644 index 00000000000..d27dafb8b4a --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs @@ -0,0 +1,35 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_validation_exception_error( + value: &crate::error::ValidationException, +) -> ::std::result::Result { + let mut out = ::std::string::String::new(); + let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); + crate::protocol_serde::shape_validation_exception::ser_validation_exception( + &mut object, + value, + )?; + object.finish(); + Ok(out) +} + +pub fn ser_validation_exception( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::error::ValidationException, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + if let Some(var_1) = &input.field_list { + let mut array_2 = object.key("fieldList").start_array(); + for item_3 in var_1 { + { + #[allow(unused_mut)] + let mut object_4 = array_2.value().start_object(); + crate::protocol_serde::shape_validation_exception_field::ser_validation_exception_field(&mut object_4, item_3)?; + object_4.finish(); + } + } + array_2.finish(); + } + { + object.key("message").string(input.message.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs new file mode 100644 index 00000000000..3321330af65 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs @@ -0,0 +1,13 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub fn ser_validation_exception_field( + object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, + input: &crate::model::ValidationExceptionField, +) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { + { + object.key("path").string(input.path.as_str()); + } + { + object.key("message").string(input.message.as_str()); + } + Ok(()) +} diff --git a/examples/pokemon-service-server-skd-patch/src/service.rs b/examples/pokemon-service-server-skd-patch/src/service.rs new file mode 100644 index 00000000000..bbaaa11f938 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/service.rs @@ -0,0 +1,1963 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +/// The service builder for [`PokemonService`]. +/// +/// Constructed via [`PokemonService::builder`]. +pub struct PokemonServiceBuilder { + capture_pokemon: Option<::aws_smithy_http_server::routing::Route>, + check_health: Option<::aws_smithy_http_server::routing::Route>, + do_nothing: Option<::aws_smithy_http_server::routing::Route>, + get_pokemon_species: Option<::aws_smithy_http_server::routing::Route>, + get_server_statistics: Option<::aws_smithy_http_server::routing::Route>, + get_storage: Option<::aws_smithy_http_server::routing::Route>, + stream_pokemon_radio: Option<::aws_smithy_http_server::routing::Route>, + layer: L, + http_plugin: HttpPl, + model_plugin: ModelPl, +} + +impl PokemonServiceBuilder { + /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::CapturePokemonInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .capture_pokemon(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn capture_pokemon(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::CapturePokemon::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.capture_pokemon_custom(svc) + } + + /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::CapturePokemonInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .capture_pokemon_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn capture_pokemon_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CapturePokemon, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::CapturePokemon::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.capture_pokemon_custom(svc) + } + + /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn capture_pokemon_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.capture_pokemon = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::CheckHealthInput) -> output::CheckHealthOutput { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .check_health(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn check_health(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::CheckHealth::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.check_health_custom(svc) + } + + /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::CheckHealthInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .check_health_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn check_health_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::CheckHealth, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::CheckHealth::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.check_health_custom(svc) + } + + /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn check_health_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.check_health = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::DoNothingInput) -> output::DoNothingOutput { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .do_nothing(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn do_nothing(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::DoNothing::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.do_nothing_custom(svc) + } + + /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::DoNothingInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .do_nothing_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn do_nothing_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::DoNothing, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::DoNothing::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.do_nothing_custom(svc) + } + + /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn do_nothing_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.do_nothing = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetPokemonSpeciesInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .get_pokemon_species(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_pokemon_species(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetPokemonSpecies::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_pokemon_species_custom(svc) + } + + /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetPokemonSpeciesInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .get_pokemon_species_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_pokemon_species_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetPokemonSpecies, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetPokemonSpecies::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_pokemon_species_custom(svc) + } + + /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn get_pokemon_species_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.get_pokemon_species = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetServerStatisticsInput) -> output::GetServerStatisticsOutput { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .get_server_statistics(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_server_statistics(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetServerStatistics::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_server_statistics_custom(svc) + } + + /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetServerStatisticsInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .get_server_statistics_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_server_statistics_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetServerStatistics, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetServerStatistics::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_server_statistics_custom(svc) + } + + /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn get_server_statistics_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.get_server_statistics = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetStorageInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .get_storage(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_storage(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetStorage::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_storage_custom(svc) + } + + /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::GetStorageInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .get_storage_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn get_storage_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::GetStorage, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::GetStorage::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.get_storage_custom(svc) + } + + /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn get_storage_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.get_storage = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } + + /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::StreamPokemonRadioInput) -> output::StreamPokemonRadioOutput { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let app = PokemonService::builder(config) + /// .stream_pokemon_radio(handler) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn stream_pokemon_radio(self, handler: HandlerType) -> Self + where + HandlerType: ::aws_smithy_http_server::operation::Handler, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ::aws_smithy_http_server::operation::IntoService + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::StreamPokemonRadio::from_handler(handler); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.stream_pokemon_radio_custom(svc) + } + + /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) operation. + /// + /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. + /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. + /// + /// # Example + /// + /// ```no_run + /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; + /// + /// use pokemon_service_server_sdk::{input, output, error}; + /// + /// async fn handler(input: input::StreamPokemonRadioInput) -> Result { + /// todo!() + /// } + /// + /// let config = PokemonServiceConfig::builder().build(); + /// let svc = ::tower::util::service_fn(handler); + /// let app = PokemonService::builder(config) + /// .stream_pokemon_radio_service(svc) + /// /* Set other handlers */ + /// .build() + /// .unwrap(); + /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; + /// ``` + /// + pub fn stream_pokemon_radio_service(self, service: S) -> Self + where + S: ::aws_smithy_http_server::operation::OperationService, + + ModelPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ::aws_smithy_http_server::operation::Normalize + >, + ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ModelPl::Output + >, + HttpPl: ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + < + ::aws_smithy_http_server::operation::UpgradePlugin:: + as ::aws_smithy_http_server::plugin::Plugin< + PokemonService, + crate::operation_shape::StreamPokemonRadio, + ModelPl::Output + > + >::Output + >, + + HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, + >>::Future: Send + 'static, + + { + use ::aws_smithy_http_server::operation::OperationShapeExt; + use ::aws_smithy_http_server::plugin::Plugin; + let svc = crate::operation_shape::StreamPokemonRadio::from_service(service); + let svc = self.model_plugin.apply(svc); + let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() + .apply(svc); + let svc = self.http_plugin.apply(svc); + self.stream_pokemon_radio_custom(svc) + } + + /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) to a custom [`Service`](tower::Service). + /// not constrained by the Smithy contract. + fn stream_pokemon_radio_custom(mut self, svc: S) -> Self + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = ::std::convert::Infallible, + > + Clone + + Send + + 'static, + S::Future: Send + 'static, + { + self.stream_pokemon_radio = Some(::aws_smithy_http_server::routing::Route::new(svc)); + self + } +} + +impl PokemonServiceBuilder { + /// Constructs a [`PokemonService`] from the arguments provided to the builder. + /// + /// Forgetting to register a handler for one or more operations will result in an error. + /// + /// Check out [`PokemonServiceBuilder::build_unchecked`] if you'd prefer the service to return status code 500 when an + /// unspecified route is requested. + pub fn build( + self, + ) -> ::std::result::Result< + PokemonService< + ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, + >, + MissingOperationsError, + > + where + L: ::tower::Layer<::aws_smithy_http_server::routing::Route>, + { + let router = { + use ::aws_smithy_http_server::operation::OperationShape; + let mut missing_operation_names = std::collections::HashMap::new(); + if self.capture_pokemon.is_none() { + missing_operation_names.insert( + crate::operation_shape::CapturePokemon::ID, + ".capture_pokemon()", + ); + } + if self.check_health.is_none() { + missing_operation_names + .insert(crate::operation_shape::CheckHealth::ID, ".check_health()"); + } + if self.do_nothing.is_none() { + missing_operation_names + .insert(crate::operation_shape::DoNothing::ID, ".do_nothing()"); + } + if self.get_pokemon_species.is_none() { + missing_operation_names.insert( + crate::operation_shape::GetPokemonSpecies::ID, + ".get_pokemon_species()", + ); + } + if self.get_server_statistics.is_none() { + missing_operation_names.insert( + crate::operation_shape::GetServerStatistics::ID, + ".get_server_statistics()", + ); + } + if self.get_storage.is_none() { + missing_operation_names + .insert(crate::operation_shape::GetStorage::ID, ".get_storage()"); + } + if self.stream_pokemon_radio.is_none() { + missing_operation_names.insert( + crate::operation_shape::StreamPokemonRadio::ID, + ".stream_pokemon_radio()", + ); + } + if !missing_operation_names.is_empty() { + return Err(MissingOperationsError { + operation_names2setter_methods: missing_operation_names, + }); + } + let unexpected_error_msg = "this should never panic since we are supposed to check beforehand that a handler has been registered for this operation; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues"; + + ::aws_smithy_http_server::protocol::rest::router::RestRouter::from_iter([ + ( + request_specs::capture_pokemon(), + self.capture_pokemon.expect(unexpected_error_msg), + ), + ( + request_specs::check_health(), + self.check_health.expect(unexpected_error_msg), + ), + ( + request_specs::do_nothing(), + self.do_nothing.expect(unexpected_error_msg), + ), + ( + request_specs::get_pokemon_species(), + self.get_pokemon_species.expect(unexpected_error_msg), + ), + ( + request_specs::get_server_statistics(), + self.get_server_statistics.expect(unexpected_error_msg), + ), + ( + request_specs::get_storage(), + self.get_storage.expect(unexpected_error_msg), + ), + ( + request_specs::stream_pokemon_radio(), + self.stream_pokemon_radio.expect(unexpected_error_msg), + ), + ]) + }; + let svc = ::aws_smithy_http_server::routing::RoutingService::new(router); + let svc = svc.map(|s| s.layer(self.layer)); + Ok(PokemonService { svc }) + } + + /// Constructs a [`PokemonService`] from the arguments provided to the builder. + /// Operations without a handler default to returning 500 Internal Server Error to the caller. + /// + /// Check out [`PokemonServiceBuilder::build`] if you'd prefer the builder to fail if one or more operations do + /// not have a registered handler. + pub fn build_unchecked(self) -> PokemonService + where + Body: Send + 'static, + L: ::tower::Layer< + ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter< + ::aws_smithy_http_server::routing::Route, + >, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, + >, + { + let router = ::aws_smithy_http_server::protocol::rest::router::RestRouter::from_iter([ + ( + request_specs::capture_pokemon(), + self.capture_pokemon.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::check_health(), + self.check_health.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::do_nothing(), + self.do_nothing.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::get_pokemon_species(), + self.get_pokemon_species.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::get_server_statistics(), + self.get_server_statistics.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::get_storage(), + self.get_storage.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ( + request_specs::stream_pokemon_radio(), + self.stream_pokemon_radio.unwrap_or_else(|| { + let svc = ::aws_smithy_http_server::operation::MissingFailure::< + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >::default(); + ::aws_smithy_http_server::routing::Route::new(svc) + }), + ), + ]); + let svc = self + .layer + .layer(::aws_smithy_http_server::routing::RoutingService::new( + router, + )); + PokemonService { svc } + } +} + +/// The error encountered when calling the [`PokemonServiceBuilder::build`] method if one or more operation handlers are not +/// specified. +#[derive(Debug)] +pub struct MissingOperationsError { + operation_names2setter_methods: + std::collections::HashMap<::aws_smithy_http_server::shape_id::ShapeId, &'static str>, +} + +impl std::fmt::Display for MissingOperationsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "You must specify a handler for all operations attached to `PokemonService`.\n\ + We are missing handlers for the following operations:\n", + )?; + for operation_name in self.operation_names2setter_methods.keys() { + writeln!(f, "- {}", operation_name.absolute())?; + } + + writeln!(f, "\nUse the dedicated methods on `PokemonServiceBuilder` to register the missing handlers:")?; + for setter_name in self.operation_names2setter_methods.values() { + writeln!(f, "- {}", setter_name)?; + } + Ok(()) + } +} + +impl std::error::Error for MissingOperationsError {} + +mod request_specs { + pub(super) fn capture_pokemon() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec + { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::POST, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("capture-pokemon-event")), + ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn check_health() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("ping")), +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn do_nothing() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("do-nothing")), +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn get_pokemon_species( + ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("pokemon-species")), + ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn get_server_statistics( + ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("stats")), +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn get_storage() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("pokedex")), + ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } + pub(super) fn stream_pokemon_radio( + ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { + ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( + ::http::Method::GET, + ::aws_smithy_http_server::routing::request_spec::UriSpec::new( + ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( + ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ + ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("radio")), +]), + ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ +]) + ) + ), + ) + } +} + +/// The Pokémon Service allows you to retrieve information about Pokémon species. +/// +/// See the [root](crate) documentation for more information. +#[derive(Clone)] +pub struct PokemonService< + S = ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter< + ::aws_smithy_http_server::routing::Route<::aws_smithy_http_server::body::BoxBody>, + >, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, +> { + // This is the router wrapped by layers. + svc: S, +} + +impl PokemonService<()> { + /// Constructs a builder for [`PokemonService`]. + /// You must specify a configuration object holding any plugins and layers that should be applied + /// to the operations in this service. + pub fn builder< + Body, + L, + HttpPl: ::aws_smithy_http_server::plugin::HttpMarker, + ModelPl: ::aws_smithy_http_server::plugin::ModelMarker, + >( + config: PokemonServiceConfig, + ) -> PokemonServiceBuilder { + PokemonServiceBuilder { + capture_pokemon: None, + check_health: None, + do_nothing: None, + get_pokemon_species: None, + get_server_statistics: None, + get_storage: None, + stream_pokemon_radio: None, + layer: config.layers, + http_plugin: config.http_plugins, + model_plugin: config.model_plugins, + } + } + + /// Constructs a builder for [`PokemonService`]. + /// You must specify what plugins should be applied to the operations in this service. + /// + /// Use [`PokemonService::builder_without_plugins`] if you don't need to apply plugins. + /// + /// Check out [`HttpPlugins`](::aws_smithy_http_server::plugin::HttpPlugins) and + /// [`ModelPlugins`](::aws_smithy_http_server::plugin::ModelPlugins) if you need to apply + /// multiple plugins. + #[deprecated( + since = "0.57.0", + note = "please use the `builder` constructor and register plugins on the `PokemonServiceConfig` object instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" + )] + pub fn builder_with_plugins< + Body, + HttpPl: ::aws_smithy_http_server::plugin::HttpMarker, + ModelPl: ::aws_smithy_http_server::plugin::ModelMarker, + >( + http_plugin: HttpPl, + model_plugin: ModelPl, + ) -> PokemonServiceBuilder { + PokemonServiceBuilder { + capture_pokemon: None, + check_health: None, + do_nothing: None, + get_pokemon_species: None, + get_server_statistics: None, + get_storage: None, + stream_pokemon_radio: None, + layer: ::tower::layer::util::Identity::new(), + http_plugin, + model_plugin, + } + } + + /// Constructs a builder for [`PokemonService`]. + /// + /// Use [`PokemonService::builder_with_plugins`] if you need to specify plugins. + #[deprecated( + since = "0.57.0", + note = "please use the `builder` constructor instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" + )] + pub fn builder_without_plugins() -> PokemonServiceBuilder< + Body, + ::tower::layer::util::Identity, + ::aws_smithy_http_server::plugin::IdentityPlugin, + ::aws_smithy_http_server::plugin::IdentityPlugin, + > { + Self::builder_with_plugins( + ::aws_smithy_http_server::plugin::IdentityPlugin, + ::aws_smithy_http_server::plugin::IdentityPlugin, + ) + } +} + +impl PokemonService { + /// Converts [`PokemonService`] into a [`MakeService`](tower::make::MakeService) with [`ConnectInfo`](::aws_smithy_http_server::request::connect_info::ConnectInfo). + pub fn into_make_service_with_connect_info( + self, + ) -> ::aws_smithy_http_server::routing::IntoMakeServiceWithConnectInfo { + ::aws_smithy_http_server::routing::IntoMakeServiceWithConnectInfo::new(self) + } +} + +impl + PokemonService< + ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, + > +{ + /// Applies a [`Layer`](::tower::Layer) uniformly to all routes. + #[deprecated( + since = "0.57.0", + note = "please add layers to the `PokemonServiceConfig` object instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" + )] + pub fn layer( + self, + layer: &L, + ) -> PokemonService< + ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, + > + where + L: ::tower::Layer, + { + PokemonService { + svc: self.svc.map(|s| s.layer(layer)), + } + } + + /// Applies [`Route::new`](::aws_smithy_http_server::routing::Route::new) to all routes. + /// + /// This has the effect of erasing all types accumulated via layers. + pub fn boxed( + self, + ) -> PokemonService< + ::aws_smithy_http_server::routing::RoutingService< + ::aws_smithy_http_server::protocol::rest::router::RestRouter< + ::aws_smithy_http_server::routing::Route, + >, + ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, + >, + > + where + S: ::tower::Service< + ::http::Request, + Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, + Error = std::convert::Infallible, + >, + S: Clone + Send + 'static, + S::Future: Send + 'static, + { + self.layer(&::tower::layer::layer_fn( + ::aws_smithy_http_server::routing::Route::new, + )) + } +} + +impl ::tower::Service for PokemonService +where + S: ::tower::Service, +{ + type Response = S::Response; + type Error = S::Error; + type Future = S::Future; + + fn poll_ready( + &mut self, + cx: &mut std::task::Context, + ) -> std::task::Poll<::std::result::Result<(), Self::Error>> { + self.svc.poll_ready(cx) + } + + fn call(&mut self, request: R) -> Self::Future { + self.svc.call(request) + } +} + +/// An enumeration of all [operations](https://smithy.io/2.0/spec/service-types.html#operation) in PokemonService. +#[allow(clippy::enum_variant_names)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Operation { + CapturePokemon, + CheckHealth, + DoNothing, + GetPokemonSpecies, + GetServerStatistics, + GetStorage, + StreamPokemonRadio, +} + +impl Operation { + /// Returns the [operations](https://smithy.io/2.0/spec/service-types.html#operation) [`ShapeId`](::aws_smithy_http_server::shape_id::ShapeId). + pub fn shape_id(&self) -> ::aws_smithy_http_server::shape_id::ShapeId { + match self { + Operation::CapturePokemon => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#CapturePokemon", + "com.aws.example", + "CapturePokemon", + ), + Operation::CheckHealth => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#CheckHealth", + "com.aws.example", + "CheckHealth", + ), + Operation::DoNothing => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#DoNothing", + "com.aws.example", + "DoNothing", + ), + Operation::GetPokemonSpecies => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetPokemonSpecies", + "com.aws.example", + "GetPokemonSpecies", + ), + Operation::GetServerStatistics => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetServerStatistics", + "com.aws.example", + "GetServerStatistics", + ), + Operation::GetStorage => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#GetStorage", + "com.aws.example", + "GetStorage", + ), + Operation::StreamPokemonRadio => ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#StreamPokemonRadio", + "com.aws.example", + "StreamPokemonRadio", + ), + } + } +} +impl ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::CapturePokemon; +} +impl ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::CheckHealth; +} +impl ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::DoNothing; +} +impl + ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::GetPokemonSpecies; +} +impl + ::aws_smithy_http_server::service::ContainsOperation< + crate::operation_shape::GetServerStatistics, + > for PokemonService +{ + const VALUE: Operation = Operation::GetServerStatistics; +} +impl ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::GetStorage; +} +impl + ::aws_smithy_http_server::service::ContainsOperation + for PokemonService +{ + const VALUE: Operation = Operation::StreamPokemonRadio; +} + +impl ::aws_smithy_http_server::service::ServiceShape for PokemonService { + const ID: ::aws_smithy_http_server::shape_id::ShapeId = + ::aws_smithy_http_server::shape_id::ShapeId::new( + "com.aws.example#PokemonService", + "com.aws.example", + "PokemonService", + ); + + const VERSION: Option<&'static str> = Some("2024-03-18"); + + type Protocol = ::aws_smithy_http_server::protocol::rest_json_1::RestJson1; + + type Operations = Operation; +} +/// Configuration for the [`PokemonService`]. This is the central place where to register and +/// configure [`::tower::Layer`]s, HTTP plugins, and model plugins. +/// +/// ```rust,no_run +/// # use pokemon_service_server_sdk::PokemonServiceConfig; +/// # use ::aws_smithy_http_server::plugin::IdentityPlugin; +/// # use ::tower::layer::util::Identity; +/// # let authentication_plugin = IdentityPlugin; +/// # let authorization_plugin = IdentityPlugin; +/// # let server_request_id_provider_layer = Identity::new(); +/// let config = PokemonServiceConfig::builder() +/// // Layers get executed first... +/// .layer(server_request_id_provider_layer) +/// // ...then HTTP plugins... +/// .http_plugin(authentication_plugin) +/// // ...and right after deserialization, model plugins. +/// .model_plugin(authorization_plugin) +/// .build(); +/// ``` +/// +/// See the [`plugin`] system for details. +/// +/// [`plugin`]: ::aws_smithy_http_server::plugin +#[derive(::std::fmt::Debug)] +pub struct PokemonServiceConfig { + layers: L, + http_plugins: H, + model_plugins: M, +} + +impl PokemonServiceConfig<(), (), ()> { + /// Returns a builder to construct the configuration. + pub fn builder() -> PokemonServiceConfigBuilder< + ::tower::layer::util::Identity, + ::aws_smithy_http_server::plugin::IdentityPlugin, + ::aws_smithy_http_server::plugin::IdentityPlugin, + > { + PokemonServiceConfigBuilder { + layers: ::tower::layer::util::Identity::new(), + http_plugins: ::aws_smithy_http_server::plugin::IdentityPlugin, + model_plugins: ::aws_smithy_http_server::plugin::IdentityPlugin, + } + } +} + +/// Builder returned by [`PokemonServiceConfig::builder()`]. +#[derive(::std::fmt::Debug)] +pub struct PokemonServiceConfigBuilder { + pub(crate) layers: L, + pub(crate) http_plugins: H, + pub(crate) model_plugins: M, +} + +impl PokemonServiceConfigBuilder { + /// Add a [`::tower::Layer`] to the service. + pub fn layer( + self, + layer: NewLayer, + ) -> PokemonServiceConfigBuilder<::tower::layer::util::Stack, H, M> { + PokemonServiceConfigBuilder { + layers: ::tower::layer::util::Stack::new(layer, self.layers), + http_plugins: self.http_plugins, + model_plugins: self.model_plugins, + } + } + + /// Add a HTTP [plugin] to the service. + /// + /// [plugin]: ::aws_smithy_http_server::plugin + // We eagerly require `NewPlugin: HttpMarker`, despite not really needing it, because compiler + // errors get _substantially_ better if the user makes a mistake. + pub fn http_plugin( + self, + http_plugin: NewPlugin, + ) -> PokemonServiceConfigBuilder< + L, + ::aws_smithy_http_server::plugin::PluginStack, + M, + > { + PokemonServiceConfigBuilder { + layers: self.layers, + http_plugins: ::aws_smithy_http_server::plugin::PluginStack::new( + http_plugin, + self.http_plugins, + ), + model_plugins: self.model_plugins, + } + } + + /// Add a model [plugin] to the service. + /// + /// [plugin]: ::aws_smithy_http_server::plugin + // We eagerly require `NewPlugin: ModelMarker`, despite not really needing it, because compiler + // errors get _substantially_ better if the user makes a mistake. + pub fn model_plugin( + self, + model_plugin: NewPlugin, + ) -> PokemonServiceConfigBuilder< + L, + H, + ::aws_smithy_http_server::plugin::PluginStack, + > { + PokemonServiceConfigBuilder { + layers: self.layers, + http_plugins: self.http_plugins, + model_plugins: ::aws_smithy_http_server::plugin::PluginStack::new( + model_plugin, + self.model_plugins, + ), + } + } + + /// Build the configuration. + pub fn build(self) -> super::PokemonServiceConfig { + super::PokemonServiceConfig { + layers: self.layers, + http_plugins: self.http_plugins, + model_plugins: self.model_plugins, + } + } +} +/// A macro to help with scoping [plugins](crate::server::plugin) to a subset of all operations. +/// +/// In contrast to [`crate::server::scope`](crate::server::scope), this macro has knowledge +/// of the service and any operations _not_ specified will be placed in the opposing group. +/// +/// # Example +/// +/// ```rust +/// scope! { +/// /// Includes [`CapturePokemon`], excluding all other operations. +/// struct ScopeA { +/// includes: [CapturePokemon] +/// } +/// } +/// +/// scope! { +/// /// Excludes [`CapturePokemon`], excluding all other operations. +/// struct ScopeB { +/// excludes: [CapturePokemon] +/// } +/// } +/// +/// # use pokemon_service_server_sdk::server::plugin::{Plugin, Scoped}; +/// # use pokemon_service_server_sdk::scope; +/// # struct MockPlugin; +/// # impl Plugin for MockPlugin { type Output = u32; fn apply(&self, input: T) -> u32 { 3 } } +/// # let scoped_a = Scoped::new::(MockPlugin); +/// # let scoped_b = Scoped::new::(MockPlugin); +/// # let a = Plugin::<(), pokemon_service_server_sdk::operation_shape::CapturePokemon, u64>::apply(&scoped_a, 6); +/// # let b = Plugin::<(), pokemon_service_server_sdk::operation_shape::CapturePokemon, u64>::apply(&scoped_b, 6); +/// # assert_eq!(a, 3_u32); +/// # assert_eq!(b, 6_u64); +/// ``` +#[macro_export] +macro_rules! scope { + // Completed, render impls + (@ $ name: ident, $ contains: ident () ($($ temp: ident)*) ($($ not_member: ident)*)) => { + $( + impl $ crate::server::plugin::scoped::Membership<$ temp> for $ name { + type Contains = $ crate::server::plugin::scoped::$ contains; + } + )* + $( + impl $ crate::server::plugin::scoped::Membership<$ not_member> for $ name { + type Contains = $ crate::server::plugin::scoped::$ contains; + } + )* + }; + // All `not_member`s exhausted, move `temp` into `not_member` + (@ $ name: ident, $ contains: ident ($($ member: ident)*) ($($ temp: ident)*) ()) => { + scope! { @ $ name, $ contains ($($ member)*) () ($($ temp)*) } + }; + + // CapturePokemon match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (CapturePokemon $($ member: ident)*) ($($ temp: ident)*) (CapturePokemon $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // CapturePokemon match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (CapturePokemon $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (CapturePokemon $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // CheckHealth match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (CheckHealth $($ member: ident)*) ($($ temp: ident)*) (CheckHealth $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // CheckHealth match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (CheckHealth $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (CheckHealth $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // DoNothing match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (DoNothing $($ member: ident)*) ($($ temp: ident)*) (DoNothing $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // DoNothing match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (DoNothing $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (DoNothing $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // GetPokemonSpecies match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (GetPokemonSpecies $($ member: ident)*) ($($ temp: ident)*) (GetPokemonSpecies $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // GetPokemonSpecies match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (GetPokemonSpecies $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (GetPokemonSpecies $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // GetServerStatistics match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (GetServerStatistics $($ member: ident)*) ($($ temp: ident)*) (GetServerStatistics $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // GetServerStatistics match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (GetServerStatistics $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (GetServerStatistics $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // GetStorage match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (GetStorage $($ member: ident)*) ($($ temp: ident)*) (GetStorage $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // GetStorage match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (GetStorage $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (GetStorage $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + // StreamPokemonRadio match found, pop from both `member` and `not_member` + (@ $ name: ident, $ contains: ident (StreamPokemonRadio $($ member: ident)*) ($($ temp: ident)*) (StreamPokemonRadio $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } + }; + // StreamPokemonRadio match not found, pop from `not_member` into `temp` stack + (@ $ name: ident, $ contains: ident (StreamPokemonRadio $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { + scope! { @ $ name, $ contains (StreamPokemonRadio $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } + }; + + ( + $(#[$ attrs:meta])* + $ vis:vis struct $ name:ident { + includes: [$($ include:ident),*] + } + ) => { + use $ crate::operation_shape::*; + $ crate::server::scope! { + $(#[$ attrs])* + $ vis struct $ name { + includes: [$($ include),*], + excludes: [] + } + } + scope! { @ $ name, False ($($ include)*) () (CapturePokemon CheckHealth DoNothing GetPokemonSpecies GetServerStatistics GetStorage StreamPokemonRadio) } + }; + ( + $(#[$ attrs:meta])* + $ vis:vis struct $ name:ident { + excludes: [$($ exclude:ident),*] + } + ) => { + use $ crate::operation_shape::*; + + $ crate::server::scope! { + $(#[$ attrs])* + $ vis struct $ name { + includes: [], + excludes: [$($ exclude),*] + } + } + scope! { @ $ name, True ($($ exclude)*) () (CapturePokemon CheckHealth DoNothing GetPokemonSpecies GetServerStatistics GetStorage StreamPokemonRadio) } + }; + } diff --git a/examples/pokemon-service-server-skd-patch/src/types.rs b/examples/pokemon-service-server-skd-patch/src/types.rs new file mode 100644 index 00000000000..0dc25aa3b50 --- /dev/null +++ b/examples/pokemon-service-server-skd-patch/src/types.rs @@ -0,0 +1,13 @@ +// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. +pub use ::aws_smithy_types::body::SdkBody; +pub use ::aws_smithy_types::byte_stream::error::Error as ByteStreamError; +pub use ::aws_smithy_types::byte_stream::AggregatedBytes; +pub use ::aws_smithy_types::byte_stream::ByteStream; +#[cfg(feature = "rt-tokio")] +pub use ::aws_smithy_types::byte_stream::FsBuilder; +#[cfg(feature = "rt-tokio")] +pub use ::aws_smithy_types::byte_stream::Length; +pub use ::aws_smithy_types::date_time::Format as DateTimeFormat; +pub use ::aws_smithy_types::error::display::DisplayErrorContext; +pub use ::aws_smithy_types::Blob; +pub use ::aws_smithy_types::DateTime; diff --git a/examples/pokemon-service-tls/Cargo.toml b/examples/pokemon-service-tls/Cargo.toml index 81c746e0411..a6eef43df5b 100644 --- a/examples/pokemon-service-tls/Cargo.toml +++ b/examples/pokemon-service-tls/Cargo.toml @@ -8,16 +8,17 @@ description = "A smithy Rust service to retrieve information about Pokémon." [dependencies] clap = { version = "4.1.11", features = ["derive"] } -hyper = { version = "0.14.26", features = ["server"] } -tokio = "1.26.0" +http = "1" +hyper = { version = "1", features = ["server"] } +hyper-util = { version = "0.1", features = ["tokio", "server", "server-auto", "service"] } +tokio = { version = "1.26.0", features = ["rt-multi-thread", "macros"] } tracing = "0.1" +tower = "0.4" # These dependencies are only required for the `pokemon-service-tls` program. - -# Latest version supporting hyper 0.x -tls-listener = { version = "0.8", features = ["rustls", "hyper-h2"] } -tokio-rustls = "0.24" -rustls-pemfile = "1" +tokio-rustls = "0.26" +rustls = "0.23" +rustls-pemfile = "2" futures-util = { version = "0.3.29", default-features = false } # Local paths @@ -29,12 +30,11 @@ assert_cmd = "2.0" serial_test = "3.1.1" # These dependencies are only required for testing the `pokemon-service-tls` program. -hyper-rustls = { version = "0.24", features = ["http2"] } -hyper-tls = { version = "0.5" } +hyper-rustls = { version = "0.27", features = ["http2"] } # Local paths -aws-smithy-http = { path = "../../rust-runtime/aws-smithy-http/" } -aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime", features = ["client", "connector-hyper-0-14-x"] } +aws-smithy-http-client = { path = "../../rust-runtime/aws-smithy-http-client", features = ["default-client", "rustls-aws-lc"] } +aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime", features = ["client", "default-https-client"] } aws-smithy-types = { path = "../../rust-runtime/aws-smithy-types/" } pokemon-service-client = { path = "../pokemon-service-client/", features = [ "behavior-version-latest", diff --git a/examples/pokemon-service-tls/src/main.rs b/examples/pokemon-service-tls/src/main.rs index 19d05119dc5..2a95d1fe53e 100644 --- a/examples/pokemon-service-tls/src/main.rs +++ b/examples/pokemon-service-tls/src/main.rs @@ -22,12 +22,20 @@ // note that by default created certificates will be unknown and you should use `-k|--insecure` // flag while making requests with cURL or you can run `mkcert -install` to trust certificates created by `mkcert`. -use std::{fs::File, future, io::BufReader, net::SocketAddr, sync::Arc}; +use std::{ + fs::File, + io::{self, BufReader}, + net::SocketAddr, + sync::Arc, +}; use clap::Parser; -use futures_util::stream::StreamExt; +use tokio::net::TcpListener; use tokio_rustls::{ - rustls::{Certificate, PrivateKey, ServerConfig}, + rustls::{ + pki_types::{CertificateDer, PrivateKeyDer}, + ServerConfig, + }, TlsAcceptor, }; @@ -37,10 +45,16 @@ use pokemon_service_common::{ }; use pokemon_service_server_sdk::{ input, output, - server::{request::connect_info::ConnectInfo, routing::Connected, AddExtensionLayer}, + server::{ + request::connect_info::ConnectInfo, + routing::Connected, + serve::{serve, Listener}, + AddExtensionLayer, + }, PokemonService, PokemonServiceConfig, }; use pokemon_service_tls::{DEFAULT_ADDRESS, DEFAULT_PORT, DEFAULT_TEST_CERT, DEFAULT_TEST_KEY}; +use tokio::net::TcpStream; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] @@ -59,6 +73,48 @@ struct Args { tls_key_path: String, } +/// A TLS listener that wraps TcpListener and TlsAcceptor +pub struct TlsListener { + tcp_listener: TcpListener, + tls_acceptor: TlsAcceptor, +} + +impl TlsListener { + pub fn new(tcp_listener: TcpListener, tls_acceptor: TlsAcceptor) -> Self { + Self { + tcp_listener, + tls_acceptor, + } + } +} + +impl Listener for TlsListener { + type Io = tokio_rustls::server::TlsStream; + type Addr = SocketAddr; + + async fn accept(&mut self) -> (Self::Io, Self::Addr) { + loop { + match self.tcp_listener.accept().await { + Ok((tcp_stream, remote_addr)) => match self.tls_acceptor.accept(tcp_stream).await { + Ok(tls_stream) => return (tls_stream, remote_addr), + Err(err) => { + eprintln!("TLS handshake failed: {err}"); + continue; + } + }, + Err(err) => { + eprintln!("Failed to accept TCP connection: {err}"); + tokio::time::sleep(std::time::Duration::from_millis(100)).await; + } + } + } + } + + fn local_addr(&self) -> io::Result { + self.tcp_listener.local_addr() + } +} + /// Information derived from the TLS connection. #[derive(Debug, Clone)] pub struct TlsConnectInfo { @@ -66,19 +122,21 @@ pub struct TlsConnectInfo { pub socket_addr: SocketAddr, /// The set of TLS certificates presented by the peer in this connection. - pub certs: Option>>, + pub certs: Option>>>, } -impl Connected<&tokio_rustls::server::TlsStream> +impl<'a> Connected> for TlsConnectInfo { fn connect_info( - target: &tokio_rustls::server::TlsStream, + target: pokemon_service_server_sdk::server::serve::IncomingStream<'a, TlsListener>, ) -> Self { - let (addr_stream, session) = target.get_ref(); - let socket_addr = addr_stream.remote_addr(); + let tls_stream = target.io(); + let socket_addr = *target.remote_addr(); - let certs = session + let certs = tls_stream + .get_ref() + .1 .peer_certificates() .map(|certs| Arc::new(certs.to_vec())); @@ -126,27 +184,26 @@ pub async fn main() { .parse() .expect("unable to parse the server bind address and port"); - let acceptor = acceptor(&args.tls_cert_path, &args.tls_key_path); - let listener = tls_listener::TlsListener::new( - acceptor, - hyper::server::conn::AddrIncoming::bind(&addr).expect("could not bind"), - ) - .connections() - .filter(|conn| { - if let Err(err) = conn { - eprintln!("connection error: {:?}", err); - future::ready(false) - } else { - future::ready(true) - } - }); + let tls_acceptor = acceptor(&args.tls_cert_path, &args.tls_key_path); + let tcp_listener = TcpListener::bind(addr) + .await + .expect("failed to bind TCP listener"); + + // Get the actual bound address (important when port 0 is used for random port) + let actual_addr = tcp_listener.local_addr().expect("failed to get local address"); + + let tls_listener = TlsListener::new(tcp_listener, tls_acceptor); + + // Signal that the server is ready to accept connections, including the actual port + eprintln!("SERVER_READY:{}", actual_addr.port()); + // Using `into_make_service_with_connect_info`, rather than `into_make_service`, to adjoin the `TlsConnectInfo` // connection info. let make_app = app.into_make_service_with_connect_info::(); - let server = - hyper::Server::builder(hyper::server::accept::from_stream(listener)).serve(make_app); - if let Err(err) = server.await { - eprintln!("server error: {}", err); + + // Run the server using the serve function + if let Err(err) = serve(tls_listener, make_app).await { + eprintln!("server error: {err}"); } } @@ -156,7 +213,6 @@ pub fn acceptor(cert_path: &str, key_path: &str) -> TlsAcceptor { let certs = load_certs(cert_path); let key = load_key(key_path); let mut server_config = ServerConfig::builder() - .with_safe_defaults() .with_no_client_auth() .with_single_cert(certs, key) .expect("could not create server config"); @@ -167,22 +223,20 @@ pub fn acceptor(cert_path: &str, key_path: &str) -> TlsAcceptor { TlsAcceptor::from(Arc::new(server_config)) } -fn load_certs(path: &str) -> Vec { +fn load_certs(path: &str) -> Vec> { let mut reader = BufReader::new(File::open(path).expect("could not open certificate")); rustls_pemfile::certs(&mut reader) + .collect::, _>>() .expect("could not parse certificate") - .into_iter() - .map(Certificate) - .collect() } -fn load_key(path: &str) -> PrivateKey { +fn load_key(path: &str) -> PrivateKeyDer<'static> { let mut reader = BufReader::new(File::open(path).expect("could not open private key")); loop { match rustls_pemfile::read_one(&mut reader).expect("could not parse private key") { - Some(rustls_pemfile::Item::RSAKey(key)) => return PrivateKey(key), - Some(rustls_pemfile::Item::PKCS8Key(key)) => return PrivateKey(key), - Some(rustls_pemfile::Item::ECKey(key)) => return PrivateKey(key), + Some(rustls_pemfile::Item::Pkcs1Key(key)) => return key.into(), + Some(rustls_pemfile::Item::Pkcs8Key(key)) => return key.into(), + Some(rustls_pemfile::Item::Sec1Key(key)) => return key.into(), None => break, _ => {} } diff --git a/examples/pokemon-service-tls/tests/common/mod.rs b/examples/pokemon-service-tls/tests/common/mod.rs index 8954365a205..2cce4127e7d 100644 --- a/examples/pokemon-service-tls/tests/common/mod.rs +++ b/examples/pokemon-service-tls/tests/common/mod.rs @@ -3,79 +3,85 @@ * SPDX-License-Identifier: Apache-2.0 */ -use std::{fs::File, io::BufReader, process::Command, time::Duration}; +use std::{ + io::{BufRead, BufReader}, + process::{Command, Stdio}, + time::Duration, +}; -use assert_cmd::prelude::*; -use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; -use tokio::time::sleep; +use aws_smithy_http_client::{Builder, tls}; +use tokio::time::timeout; use pokemon_service_client::{Client, Config}; use pokemon_service_common::ChildDrop; -use pokemon_service_tls::{DEFAULT_DOMAIN, DEFAULT_PORT, DEFAULT_TEST_CERT}; +use pokemon_service_tls::{DEFAULT_DOMAIN, DEFAULT_TEST_CERT}; -pub async fn run_server() -> ChildDrop { - let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); - let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); +pub struct ServerHandle { + pub child: ChildDrop, + pub port: u16, +} + +pub async fn run_server() -> ServerHandle { + let mut child = Command::new(assert_cmd::cargo::cargo_bin!("pokemon-service-tls")) + .args(["--port", "0"]) // Use port 0 for random available port + .stderr(Stdio::piped()) + .spawn() + .unwrap(); - sleep(Duration::from_millis(500)).await; + // Wait for the server to signal it's ready by reading stderr + let stderr = child.stderr.take().unwrap(); + let ready_signal = tokio::task::spawn_blocking(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + if let Ok(line) = line { + if let Some(port_str) = line.strip_prefix("SERVER_READY:") { + if let Ok(port) = port_str.parse::() { + return Some(port); + } + } + } + } + None + }); - ChildDrop(child) + // Wait for the ready signal with a timeout + let port = match timeout(Duration::from_secs(5), ready_signal).await { + Ok(Ok(Some(port))) => port, + _ => { + panic!("Server did not become ready within 5 seconds"); + } + }; + + ServerHandle { + child: ChildDrop(child), + port, + } } // Returns a client that only talks through https and http2 connections. // It is useful in testing whether our server can talk to http2. -pub fn client_http2_only() -> Client { +pub fn client_http2_only(port: u16) -> Client { // Create custom cert store and add our test certificate to prevent unknown cert issues. - let mut reader = - BufReader::new(File::open(DEFAULT_TEST_CERT).expect("could not open certificate")); - let certs = rustls_pemfile::certs(&mut reader).expect("could not parse certificate"); - let mut roots = tokio_rustls::rustls::RootCertStore::empty(); - roots.add_parsable_certificates(&certs); - - let connector = hyper_rustls::HttpsConnectorBuilder::new() - .with_tls_config( - tokio_rustls::rustls::ClientConfig::builder() - .with_safe_defaults() - .with_root_certificates(roots) - .with_no_client_auth(), - ) - .https_only() - .enable_http2() - .build(); - - let config = Config::builder() - .http_client(HyperClientBuilder::new().build(connector)) - .endpoint_url(format!("https://{DEFAULT_DOMAIN}:{DEFAULT_PORT}")) - .build(); - Client::from_conf(config) -} - -/// A `hyper` connector that uses the `native-tls` crate for TLS. To use this in a Smithy client, -/// wrap with a [`HyperClientBuilder`]. -pub type NativeTlsConnector = hyper_tls::HttpsConnector; + let cert_pem = std::fs::read(DEFAULT_TEST_CERT).expect("could not open certificate"); -fn native_tls_connector() -> NativeTlsConnector { - let cert = hyper_tls::native_tls::Certificate::from_pem( - std::fs::read_to_string(DEFAULT_TEST_CERT) - .expect("could not open certificate") - .as_bytes(), - ) - .expect("could not parse certificate"); + let trust_store = tls::TrustStore::empty() + .with_native_roots(false) + .with_pem_certificate(cert_pem); - let tls_connector = hyper_tls::native_tls::TlsConnector::builder() - .min_protocol_version(Some(hyper_tls::native_tls::Protocol::Tlsv12)) - .add_root_certificate(cert) + let tls_context = tls::TlsContext::builder() + .with_trust_store(trust_store) .build() - .unwrap_or_else(|e| panic!("error while creating TLS connector: {}", e)); - let mut http_connector = hyper::client::HttpConnector::new(); - http_connector.enforce_http(false); - hyper_tls::HttpsConnector::from((http_connector, tls_connector.into())) -} + .expect("failed to build TLS context"); + + let http_client = Builder::new() + .tls_provider(tls::Provider::Rustls(tls::rustls_provider::CryptoMode::AwsLc)) + .tls_context(tls_context) + .build_https(); -pub fn native_tls_client() -> Client { let config = Config::builder() - .http_client(HyperClientBuilder::new().build(native_tls_connector())) - .endpoint_url(format!("https://{DEFAULT_DOMAIN}:{DEFAULT_PORT}")) + .http_client(http_client) + .endpoint_url(format!("https://{DEFAULT_DOMAIN}:{port}")) .build(); Client::from_conf(config) } + diff --git a/examples/pokemon-service-tls/tests/custom_connectors.rs b/examples/pokemon-service-tls/tests/custom_connectors.rs index a65881afe10..e8b8006ef0b 100644 --- a/examples/pokemon-service-tls/tests/custom_connectors.rs +++ b/examples/pokemon-service-tls/tests/custom_connectors.rs @@ -5,25 +5,12 @@ pub mod common; -use serial_test::serial; - // This test invokes an operation with a client that can only send HTTP2 requests and whose TLS // implementation is backed by `rustls`. #[tokio::test] -#[serial] async fn test_do_nothing_http2_rustls_connector() { - let _child = common::run_server().await; - let client = common::client_http2_only(); - - let _check_health = client.do_nothing().send().await.unwrap(); -} - -// This test invokes an operation with a client whose TLS implementation is backed by `native_tls`. -#[tokio::test] -#[serial] -async fn test_do_nothing_native_tls_connector() { - let _child = common::run_server().await; - let client = common::native_tls_client(); + let server = common::run_server().await; + let client = common::client_http2_only(server.port); let _check_health = client.do_nothing().send().await.unwrap(); } diff --git a/examples/pokemon-service/Cargo.toml b/examples/pokemon-service/Cargo.toml index 5afe717c6ba..e8b9fc26e0b 100644 --- a/examples/pokemon-service/Cargo.toml +++ b/examples/pokemon-service/Cargo.toml @@ -8,9 +8,10 @@ description = "A smithy Rust service to retrieve information about Pokémon." [dependencies] clap = { version = "4", features = ["derive"] } -http = "0.2" -hyper = { version = "0.14.26", features = ["server"] } -tokio = "1.26.0" +http = "1" +hyper = { version = "1", features = ["server"] } +hyper-util = { version = "0.1", features = ["tokio", "server", "server-auto", "service"] } +tokio = { version = "1.26.0", features = ["rt-multi-thread", "macros"] } tower = "0.4" tracing = "0.1" @@ -21,17 +22,20 @@ pokemon-service-common = { path = "../pokemon-service-common/" } [dev-dependencies] assert_cmd = "2.0" async-stream = "0.3" +bytes = "1" +http-body-util = "0.1" rand = "0.8.5" serial_test = "3.1.1" # We use hyper client in tests -hyper = { version = "0.14.26", features = ["server", "client"] } +hyper = { version = "1", features = ["server", "client"] } +hyper-util = { version = "0.1", features = ["client", "client-legacy", "http1", "http2"] } # This dependency is only required for testing the `pokemon-service-tls` program. -hyper-rustls = { version = "0.24", features = ["http2"] } +hyper-rustls = { version = "0.27", features = ["http2"] } # Local paths -aws-smithy-http = { path = "../../rust-runtime/aws-smithy-http/" } +aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime" } pokemon-service-client = { path = "../pokemon-service-client/", features = [ "behavior-version-latest", ] } diff --git a/examples/pokemon-service/src/main.rs b/examples/pokemon-service/src/main.rs index 4420553a4d1..6cc453a61bb 100644 --- a/examples/pokemon-service/src/main.rs +++ b/examples/pokemon-service/src/main.rs @@ -15,10 +15,11 @@ use pokemon_service_server_sdk::server::{ layer::alb_health_check::AlbHealthCheckLayer, plugin::{HttpPlugins, ModelPlugins, Scoped}, request::request_id::ServerRequestIdProviderLayer, - AddExtensionLayer, + serve, AddExtensionLayer, }; +use tokio::net::TcpListener; -use hyper::StatusCode; +use http::StatusCode; use plugin::PrintExt; use pokemon_service::{ @@ -106,10 +107,18 @@ pub async fn main() { let bind: SocketAddr = format!("{}:{}", args.address, args.port) .parse() .expect("unable to parse the server bind address and port"); - let server = hyper::Server::bind(&bind).serve(make_app); + let listener = TcpListener::bind(bind) + .await + .expect("failed to bind TCP listener"); + + // Get the actual bound address (important when port 0 is used for random port) + let actual_addr = listener.local_addr().expect("failed to get local address"); + + // Signal that the server is ready to accept connections, including the actual port + eprintln!("SERVER_READY:{}", actual_addr.port()); // Run forever-ish... - if let Err(err) = server.await { - eprintln!("server error: {}", err); + if let Err(err) = serve(listener, make_app).await { + eprintln!("server error: {err}"); } } diff --git a/examples/pokemon-service/tests/common/mod.rs b/examples/pokemon-service/tests/common/mod.rs index 2d58f4a975a..d8a13280a27 100644 --- a/examples/pokemon-service/tests/common/mod.rs +++ b/examples/pokemon-service/tests/common/mod.rs @@ -3,31 +3,67 @@ * SPDX-License-Identifier: Apache-2.0 */ -use std::{process::Command, time::Duration}; +use std::{ + io::{BufRead, BufReader}, + process::{Command, Stdio}, + time::Duration, +}; -use assert_cmd::prelude::*; -use tokio::time::sleep; +use tokio::time::timeout; -use pokemon_service::{DEFAULT_ADDRESS, DEFAULT_PORT}; +use pokemon_service::DEFAULT_ADDRESS; use pokemon_service_client::{Client, Config}; use pokemon_service_common::ChildDrop; -pub async fn run_server() -> ChildDrop { - let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); - let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); +pub struct ServerHandle { + pub child: ChildDrop, + pub port: u16, +} + +pub async fn run_server() -> ServerHandle { + let mut child = Command::new(assert_cmd::cargo::cargo_bin!("pokemon-service")) + .args(["--port", "0"]) // Use port 0 for random available port + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + // Wait for the server to signal it's ready by reading stderr + let stderr = child.stderr.take().unwrap(); + let ready_signal = tokio::task::spawn_blocking(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + if let Ok(line) = line { + if let Some(port_str) = line.strip_prefix("SERVER_READY:") { + if let Ok(port) = port_str.parse::() { + return Some(port); + } + } + } + } + None + }); - sleep(Duration::from_millis(500)).await; + // Wait for the ready signal with a timeout + let port = match timeout(Duration::from_secs(5), ready_signal).await { + Ok(Ok(Some(port))) => port, + _ => { + panic!("Server did not become ready within 5 seconds"); + } + }; - ChildDrop(child) + ServerHandle { + child: ChildDrop(child), + port, + } } -pub fn base_url() -> String { - format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}") +pub fn base_url(port: u16) -> String { + format!("http://{DEFAULT_ADDRESS}:{port}") } -pub fn client() -> Client { +pub fn client(port: u16) -> Client { let config = Config::builder() - .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}")) + .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{port}")) .build(); Client::from_conf(config) } diff --git a/examples/pokemon-service/tests/event_streaming.rs b/examples/pokemon-service/tests/event_streaming.rs index 664827620bb..dd68eefed18 100644 --- a/examples/pokemon-service/tests/event_streaming.rs +++ b/examples/pokemon-service/tests/event_streaming.rs @@ -7,7 +7,6 @@ pub mod common; use async_stream::stream; use rand::Rng; -use serial_test::serial; use pokemon_service_client::types::{ error::{AttemptCapturingPokemonEventError, MasterBallUnsuccessful}, @@ -34,10 +33,9 @@ fn get_pokeball() -> String { } #[tokio::test] -#[serial] async fn event_stream_test() { - let _child = common::run_server().await; - let client = common::client(); + let server = common::run_server().await; + let client = common::client(server.port); let mut team = vec![]; let input_stream = stream! { @@ -71,7 +69,7 @@ async fn event_stream_test() { }; // Throw many! - let mut output = common::client() + let mut output = common::client(server.port) .capture_pokemon() .region("Kanto") .events(input_stream.into()) diff --git a/examples/pokemon-service/tests/simple.rs b/examples/pokemon-service/tests/simple.rs index dc9f88d0b53..2b24af7eddc 100644 --- a/examples/pokemon-service/tests/simple.rs +++ b/examples/pokemon-service/tests/simple.rs @@ -3,20 +3,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +use bytes; +use http_body_util; +use hyper_util::{client::legacy::Client, rt::TokioExecutor}; use pokemon_service_client::{ error::{DisplayErrorContext, SdkError}, operation::get_storage::GetStorageError, types::error::StorageAccessNotAuthorized, }; -use serial_test::serial; pub mod common; #[tokio::test] -#[serial] async fn simple_integration_test() { - let _child = common::run_server().await; - let client = common::client(); + let server = common::run_server().await; + let client = common::client(server.port); let service_statistics_out = client.get_server_statistics().send().await.unwrap(); assert_eq!(0, service_statistics_out.calls_count); @@ -82,38 +83,42 @@ async fn simple_integration_test() { let service_statistics_out = client.get_server_statistics().send().await.unwrap(); assert_eq!(2, service_statistics_out.calls_count); - let hyper_client = hyper::Client::new(); - let health_check_url = format!("{}/ping", common::base_url()); + let hyper_client = Client::builder(TokioExecutor::new()).build_http(); + let health_check_url = format!("{}/ping", common::base_url(server.port)); let health_check_url = hyper::Uri::try_from(health_check_url).unwrap(); - let result = hyper_client.get(health_check_url).await.unwrap(); + let request = hyper::Request::builder() + .uri(health_check_url) + .body(http_body_util::Empty::::new()) + .unwrap(); + let result = hyper_client.request(request).await.unwrap(); assert_eq!(result.status(), 200); } #[tokio::test] -#[serial] async fn health_check() { - let _child = common::run_server().await; + let server = common::run_server().await; - use pokemon_service::{DEFAULT_ADDRESS, DEFAULT_PORT}; - let url = format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}/ping"); + let url = common::base_url(server.port) + "/ping"; let uri = url.parse::().expect("invalid URL"); // Since the `/ping` route is not modeled in Smithy, we use a regular // Hyper HTTP client to make a request to it. let request = hyper::Request::builder() .uri(uri) - .body(hyper::Body::empty()) + .body(http_body_util::Empty::::new()) .expect("failed to build request"); - let response = hyper::Client::new() + let client = Client::builder(TokioExecutor::new()).build_http(); + let response = client .request(request) .await .expect("failed to get response"); assert_eq!(response.status(), hyper::StatusCode::OK); - let body = hyper::body::to_bytes(response.into_body()) + let body = http_body_util::BodyExt::collect(response.into_body()) .await - .expect("failed to read response body"); + .expect("failed to read response body") + .to_bytes(); assert!(body.is_empty()); } From 9012b4d539a2a13829a7cf34c3a842c8fdcad823 Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Sun, 2 Nov 2025 20:58:31 +0000 Subject: [PATCH 2/3] Add comprehensive http@1.x upgrade guide Provides detailed migration instructions for upgrading from http@0.2/hyper@0.14 to http@1.x/hyper@1.x including: - Dependency updates - Server initialization changes - Client connector setup - Test infrastructure improvements - Common patterns and troubleshooting - Complete migration checklist --- examples/upgrade-http1x.md | 645 +++++++++++++++++++++++++++++++++++++ 1 file changed, 645 insertions(+) create mode 100644 examples/upgrade-http1x.md diff --git a/examples/upgrade-http1x.md b/examples/upgrade-http1x.md new file mode 100644 index 00000000000..1fa9dddf5e1 --- /dev/null +++ b/examples/upgrade-http1x.md @@ -0,0 +1,645 @@ +# Upgrading from http@0.2/hyper@0.14 to http@1.x/hyper@1.x + +This guide provides a comprehensive walkthrough for upgrading your smithy-rs server applications from http@0.2.x and hyper@0.14 to http@1.x and hyper@1.x. + +## Table of Contents + +- [Overview](#overview) +- [Why Upgrade?](#why-upgrade) +- [Before You Begin](#before-you-begin) +- [Dependency Updates](#dependency-updates) +- [Server-Side Changes](#server-side-changes) +- [Client-Side Changes](#client-side-changes) +- [Test Infrastructure Updates](#test-infrastructure-updates) +- [Common Migration Patterns](#common-migration-patterns) +- [Troubleshooting](#troubleshooting) +- [Migration Checklist](#migration-checklist) + +## Overview + +The http and hyper crates have released major version updates (http@1.x and hyper@1.x) with significant API improvements and breaking changes. This guide helps you migrate your smithy-rs server applications to these new versions. + +**Key Changes:** +- http: 0.2.x → 1.x +- hyper: 0.14.x → 1.x +- New hyper-util crate for additional utilities +- aws-smithy-http-server replaces aws-smithy-legacy-http-server + +## Why Upgrade? + +- **Better Performance**: Hyper 1.x has improved performance and reduced allocations +- **Improved API**: More ergonomic and safer APIs in both http and hyper +- **Active Support**: Future updates and bug fixes will target 1.x versions +- **Ecosystem Alignment**: New libraries are targeting http@1.x and hyper@1.x +- **Security Updates**: Continued security patches for 1.x line + +## Before You Begin + +**Important Considerations:** + +1. **Breaking Changes**: This is a major version upgrade with breaking API changes +2. **Testing Required**: Thoroughly test your application after migration +3. **Gradual Migration**: Consider migrating one service at a time +4. **Legacy Examples**: The `examples/legacy/` directory contains fully working http@0.2 examples for reference + +**Compatibility:** +- Minimum Rust version: Check your generated SDK's rust-toolchain.toml +- Tokio runtime: Still compatible with tokio 1.x +- Tower middleware: Compatible with tower 0.4 + +## Dependency Updates + +### Cargo.toml Changes + +#### Server Dependencies + +**Before (http@0.2/hyper@0.14):** +```toml +[dependencies] +http = "0.2" +hyper = { version = "0.14.26", features = ["server"] } +tokio = "1.26.0" +tower = "0.4" + +# Server SDK with legacy HTTP support +pokemon-service-server-sdk = { + path = "../pokemon-service-server-sdk/", + package = "pokemon-service-server-sdk-http0x", + features = ["request-id"] +} + +[dev-dependencies] +hyper = { version = "0.14.26", features = ["server", "client"] } +hyper-rustls = { version = "0.24", features = ["http2"] } +aws-smithy-legacy-http = { path = "../../../rust-runtime/aws-smithy-legacy-http/" } +``` + +**After (http@1.x/hyper@1.x):** +```toml +[dependencies] +http = "1" +hyper = { version = "1", features = ["server"] } +hyper-util = { version = "0.1", features = ["tokio", "server", "server-auto", "service"] } +tokio = { version = "1.26.0", features = ["rt-multi-thread", "macros"] } +tower = "0.4" + +# Server SDK with http@1.x support +pokemon-service-server-sdk = { + path = "../pokemon-service-server-sdk/", + features = ["request-id"] +} + +[dev-dependencies] +bytes = "1" +http-body-util = "0.1" +hyper = { version = "1", features = ["server", "client"] } +hyper-util = { version = "0.1", features = ["client", "client-legacy", "http1", "http2"] } +hyper-rustls = { version = "0.27", features = ["http2"] } +aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime" } +``` + +**Key Changes:** +- `http`: `0.2` → `1` +- `hyper`: `0.14.26` → `1` +- **New**: `hyper-util` crate for server and client utilities +- **New**: `bytes` and `http-body-util` for body handling +- `hyper-rustls`: `0.24` → `0.27` +- Server SDK package name: no longer needs `-http0x` suffix +- Replace `aws-smithy-legacy-http` with `aws-smithy-runtime` + +#### Client Dependencies + +**Before:** +```toml +[dependencies] +aws-smithy-runtime = { version = "1.0", features = ["client"] } +aws-smithy-runtime-api = "1.0" +``` + +**After:** +```toml +[dependencies] +aws-smithy-http-client = "1.0" # Replaces direct hyper usage +aws-smithy-runtime = { version = "1.0", features = ["client"] } +aws-smithy-runtime-api = "1.0" +``` + +## Server-Side Changes + +### 1. Import Changes + +**Before:** +```rust +use hyper::StatusCode; +``` + +**After:** +```rust +use http::StatusCode; +use pokemon_service_server_sdk::server::serve; +use tokio::net::TcpListener; +``` + +**Key Points:** +- `StatusCode` and other HTTP types now come from the `http` crate, not `hyper` +- Import the `serve` helper from your server SDK +- Use `tokio::net::TcpListener` instead of hyper's built-in listener + +### 2. Server Initialization + +**Before (hyper@0.14):** +```rust +#[tokio::main] +pub async fn main() { + // ... setup config and app ... + + let make_app = app.into_make_service_with_connect_info::(); + + let bind: SocketAddr = format!("{}:{}", args.address, args.port) + .parse() + .expect("unable to parse the server bind address and port"); + + let server = hyper::Server::bind(&bind).serve(make_app); + + if let Err(err) = server.await { + eprintln!("server error: {err}"); + } +} +``` + +**After (hyper@1.x):** +```rust +#[tokio::main] +pub async fn main() { + // ... setup config and app ... + + let make_app = app.into_make_service_with_connect_info::(); + + let bind: SocketAddr = format!("{}:{}", args.address, args.port) + .parse() + .expect("unable to parse the server bind address and port"); + + let listener = TcpListener::bind(bind) + .await + .expect("failed to bind TCP listener"); + + // Optional: Get the actual bound address (useful for port 0) + let actual_addr = listener.local_addr().expect("failed to get local address"); + eprintln!("Server listening on {}", actual_addr); + + if let Err(err) = serve(listener, make_app).await { + eprintln!("server error: {err}"); + } +} +``` + +**Key Changes:** +1. Replace `hyper::Server::bind(&bind)` with `TcpListener::bind(bind).await` +2. Use the `serve()` helper function instead of `.serve(make_app)` +3. TcpListener binding is now async (requires `.await`) +4. Can get actual bound address with `.local_addr()` (useful for testing with port 0) + +### 3. Service Building + +The service building API remains the same: + +```rust +let app = PokemonService::builder(config) + .get_pokemon_species(get_pokemon_species) + .get_storage(get_storage_with_local_approved) + .get_server_statistics(get_server_statistics) + .capture_pokemon(capture_pokemon) + .do_nothing(do_nothing_but_log_request_ids) + .check_health(check_health) + .build() + .expect("failed to build an instance of PokemonService"); + +let make_app = app.into_make_service_with_connect_info::(); +``` + +No changes needed here! The service builder API is stable. + +## Client-Side Changes + +### HTTP Client Connector Setup + +**Before (hyper@0.14 with hyper-rustls):** +```rust +use aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder; +use hyper_rustls::ConfigBuilderExt; + +fn create_client() -> PokemonClient { + let tls_config = rustls::ClientConfig::builder() + .with_safe_defaults() + .with_native_roots() + .with_no_client_auth(); + + let tls_connector = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(tls_config) + .https_or_http() + .enable_http1() + .enable_http2() + .build(); + + let http_client = HyperClientBuilder::new().build(tls_connector); + + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + pokemon_service_client::Client::from_conf(config) +} +``` + +**After (http@1.x with aws-smithy-http-client):** +```rust +use aws_smithy_http_client::{Builder, tls}; + +fn create_client() -> PokemonClient { + // Create a TLS context with platform trusted root certificates + let tls_context = tls::TlsContext::builder() + .with_trust_store(tls::TrustStore::default()) + .build() + .expect("failed to build TLS context"); + + // Create an HTTP client using rustls with AWS-LC crypto provider + let http_client = Builder::new() + .tls_provider(tls::Provider::Rustls(tls::rustls_provider::CryptoMode::AwsLc)) + .tls_context(tls_context) + .build_https(); + + let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .http_client(http_client) + .build(); + + pokemon_service_client::Client::from_conf(config) +} +``` + +**Key Changes:** +1. Replace `HyperClientBuilder` with `aws_smithy_http_client::Builder` +2. Use `tls::TlsContext` and `tls::TrustStore` instead of direct rustls config +3. Specify TLS provider explicitly (Rustls with AWS-LC or Ring crypto) +4. Use `.build_https()` instead of passing a connector +5. Much simpler API with better defaults + +### Using Default Client + +If you don't need custom TLS configuration, you can use the default client: + +```rust +// Default client with system trust store +let config = pokemon_service_client::Config::builder() + .endpoint_url(POKEMON_SERVICE_URL) + .build(); + +let client = pokemon_service_client::Client::from_conf(config); +``` + +## Test Infrastructure Updates + +### Test Helpers + +**Before (http@0.14):** +```rust +use std::{process::Command, time::Duration}; +use tokio::time::sleep; + +pub async fn run_server() -> ChildDrop { + let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); + let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); + sleep(Duration::from_millis(500)).await; + ChildDrop(child) +} + +pub fn base_url() -> String { + format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}") +} + +pub fn client() -> Client { + let config = Config::builder() + .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}")) + .build(); + Client::from_conf(config) +} +``` + +**After (http@1.x with dynamic port detection):** +```rust +use std::{ + io::{BufRead, BufReader}, + process::{Command, Stdio}, + time::Duration, +}; +use tokio::time::timeout; + +pub struct ServerHandle { + pub child: ChildDrop, + pub port: u16, +} + +pub async fn run_server() -> ServerHandle { + let mut child = Command::new(assert_cmd::cargo::cargo_bin!("pokemon-service")) + .args(["--port", "0"]) // Use port 0 for random available port + .stderr(Stdio::piped()) + .spawn() + .unwrap(); + + // Wait for the server to signal it's ready by reading stderr + let stderr = child.stderr.take().unwrap(); + let ready_signal = tokio::task::spawn_blocking(move || { + let reader = BufReader::new(stderr); + for line in reader.lines() { + if let Ok(line) = line { + if let Some(port_str) = line.strip_prefix("SERVER_READY:") { + if let Ok(port) = port_str.parse::() { + return Some(port); + } + } + } + } + None + }); + + // Wait for the ready signal with a timeout + let port = match timeout(Duration::from_secs(5), ready_signal).await { + Ok(Ok(Some(port))) => port, + _ => panic!("Server did not become ready within 5 seconds"), + }; + + ServerHandle { + child: ChildDrop(child), + port, + } +} + +pub fn base_url(port: u16) -> String { + format!("http://{DEFAULT_ADDRESS}:{port}") +} + +pub fn client(port: u16) -> Client { + let config = Config::builder() + .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{port}")) + .build(); + Client::from_conf(config) +} +``` + +**Key Improvements:** +1. **Dynamic port allocation**: Use port 0 to get a random available port +2. **Server ready signaling**: Wait for server to emit "SERVER_READY:{port}" before running tests +3. **No more sleep()**: Deterministic server startup detection +4. **Better test isolation**: Each test can run on its own port +5. **Timeout protection**: Fail fast if server doesn't start + +**Update your server to emit the ready signal:** +```rust +let listener = TcpListener::bind(bind).await.expect("failed to bind TCP listener"); +let actual_addr = listener.local_addr().expect("failed to get local address"); +eprintln!("SERVER_READY:{}", actual_addr.port()); +``` + +### Test Usage + +**Before:** +```rust +#[tokio::test] +async fn test_get_pokemon_species() { + let _child = common::run_server().await; + let client = common::client(); + // ... test code ... +} +``` + +**After:** +```rust +#[tokio::test] +async fn test_get_pokemon_species() { + let server = common::run_server().await; + let client = common::client(server.port); + // ... test code ... +} +``` + +## Common Migration Patterns + +### 1. StatusCode Usage + +**Before:** +```rust +use hyper::StatusCode; + +let status = StatusCode::OK; +let status = StatusCode::NOT_FOUND; +``` + +**After:** +```rust +use http::StatusCode; + +let status = StatusCode::OK; +let status = StatusCode::NOT_FOUND; +``` + +### 2. Response Building + +**Before:** +```rust +use hyper::{Body, Response, StatusCode}; + +let response = Response::builder() + .status(StatusCode::OK) + .body(Body::from("Hello")) + .unwrap(); +``` + +**After:** +```rust +use http::{Response, StatusCode}; +use http_body_util::Full; +use bytes::Bytes; + +let response = Response::builder() + .status(StatusCode::OK) + .body(Full::new(Bytes::from("Hello"))) + .unwrap(); +``` + +### 3. Request Handling + +Most request handling code remains the same thanks to smithy-rs abstractions: + +```rust +// This works the same in both versions +pub async fn get_pokemon_species( + input: GetPokemonSpeciesInput, +) -> Result { + // Your handler code +} +``` + +### 4. Middleware and Layers + +Tower layers continue to work the same way: + +```rust +// No changes needed for tower layers +let config = PokemonServiceConfig::builder() + .layer(AddExtensionLayer::new(Arc::new(State::default()))) + .layer(AlbHealthCheckLayer::from_handler("/ping", |_req| async { + StatusCode::OK + })) + .layer(ServerRequestIdProviderLayer::new()) + .build(); +``` + +## Troubleshooting + +### Common Errors and Solutions + +#### 1. "no method named `serve` found for struct `hyper::Server`" + +**Error:** +``` +error[E0599]: no method named `serve` found for struct `hyper::Server` in the current scope +``` + +**Solution:** +Use `TcpListener` with the `serve()` function instead: +```rust +let listener = TcpListener::bind(bind).await?; +serve(listener, make_app).await?; +``` + +#### 2. "the trait `tower::Service` is not implemented" + +**Error:** +``` +error[E0277]: the trait `tower::Service>` is not implemented for `...` +``` + +**Solution:** +Make sure you're using `hyper-util` with the right features: +```toml +hyper-util = { version = "0.1", features = ["tokio", "server", "server-auto", "service"] } +``` + +#### 3. "cannot find `HyperClientBuilder` in module" + +**Error:** +``` +error[E0432]: unresolved import `aws_smithy_runtime::client::http::hyper_014::HyperClientBuilder` +``` + +**Solution:** +Use the new client builder: +```rust +use aws_smithy_http_client::Builder; + +let http_client = Builder::new() + .build_https(); +``` + +#### 4. Type mismatch with `Body` or `Bytes` + +**Error:** +``` +error[E0308]: mismatched types +expected struct `hyper::body::Incoming` +found struct `http_body_util::combinators::boxed::UnsyncBoxBody<...>` +``` + +**Solution:** +Add `http-body-util` and `bytes` dependencies: +```toml +bytes = "1" +http-body-util = "0.1" +``` + +Then use the appropriate body types from `http-body-util`. + +#### 5. Tests failing with "connection refused" + +**Problem:** +Tests start before server is ready. + +**Solution:** +Implement the server ready signaling pattern shown in [Test Infrastructure Updates](#test-infrastructure-updates). + +### Getting Help + +- **Examples**: Check the `examples/` directory for working http@1.x code +- **Legacy Examples**: Check `examples/legacy/` for http@0.2 reference +- **Documentation**: https://docs.rs/aws-smithy-http-server/ +- **GitHub Issues**: https://github.com/smithy-lang/smithy-rs/issues + +## Migration Checklist + +Use this checklist to track your migration progress: + +### Pre-Migration +- [ ] Review this guide completely +- [ ] Backup your current working code +- [ ] Review the legacy examples in `examples/legacy/` +- [ ] Identify all places using http/hyper directly +- [ ] Plan for testing time + +### Dependencies +- [ ] Update `http` from `0.2` to `1` +- [ ] Update `hyper` from `0.14` to `1` +- [ ] Add `hyper-util` with required features +- [ ] Add `bytes` and `http-body-util` if needed +- [ ] Update `hyper-rustls` if used (0.24 → 0.27) +- [ ] Update server SDK package (remove `-http0x` suffix) +- [ ] Remove `aws-smithy-legacy-http` references +- [ ] Add `aws-smithy-runtime` if needed + +### Server Code +- [ ] Change `use hyper::StatusCode` to `use http::StatusCode` +- [ ] Import `serve` from server SDK +- [ ] Import `tokio::net::TcpListener` +- [ ] Replace `hyper::Server::bind()` with `TcpListener::bind().await` +- [ ] Replace `.serve(make_app)` with `serve(listener, make_app).await` +- [ ] Add server ready signaling (optional but recommended) + +### Client Code +- [ ] Replace `HyperClientBuilder` with `aws_smithy_http_client::Builder` +- [ ] Update TLS configuration to use new API +- [ ] Test custom connector setups + +### Test Code +- [ ] Update test helpers for dynamic port allocation +- [ ] Implement server ready detection +- [ ] Update all test usages to pass port parameter +- [ ] Remove arbitrary sleep() calls + +### Validation +- [ ] Run `cargo check` - fix compilation errors +- [ ] Run `cargo test` - ensure all tests pass +- [ ] Run `cargo clippy` - address warnings +- [ ] Manual testing of all endpoints +- [ ] Load/performance testing if applicable +- [ ] Review security configurations (TLS, auth) + +### Documentation +- [ ] Update README with new dependency versions +- [ ] Update code examples in documentation +- [ ] Add migration notes for your team +- [ ] Update deployment scripts if needed + +### Deployment +- [ ] Test in development environment +- [ ] Test in staging environment +- [ ] Plan rollback strategy +- [ ] Deploy to production +- [ ] Monitor for issues + +## Conclusion + +Migrating from http@0.2/hyper@0.14 to http@1.x/hyper@1.x involves updating dependencies and making targeted changes to server initialization and client setup code. The smithy-rs abstractions shield you from many breaking changes, making the migration more straightforward than a raw hyper upgrade. + +The new versions offer improved performance, better APIs, and are the future of the Rust HTTP ecosystem. While migration requires effort, the benefits make it worthwhile. + +For additional help, consult the working examples in the `examples/` directory or reach out through GitHub issues. From 21d6619ca385d3246a7830a7d2dfebfa6fe8c45e Mon Sep 17 00:00:00 2001 From: Fahad Zubair Date: Wed, 5 Nov 2025 02:08:52 +0000 Subject: [PATCH 3/3] Remove patched SDK, update upgrade guide.md --- .../Cargo.toml | 63 - .../src/constrained.rs | 16 - .../src/error.rs | 885 -------- .../src/event_stream_serde.rs | 202 -- .../src/hyper_compat.rs | 27 - .../src/input.rs | 618 ------ .../src/lib.rs | 317 --- .../src/model.rs | 578 ----- .../src/operation.rs | 639 ------ .../src/operation_shape.rs | 289 --- .../src/output.rs | 461 ---- .../src/protocol_serde.rs | 58 - .../protocol_serde/shape_capture_pokemon.rs | 226 -- .../shape_capture_pokemon_input.rs | 29 - .../protocol_serde/shape_capturing_payload.rs | 90 - .../src/protocol_serde/shape_check_health.rs | 54 - .../src/protocol_serde/shape_do_nothing.rs | 56 - .../protocol_serde/shape_do_nothing_output.rs | 20 - .../src/protocol_serde/shape_flavor_text.rs | 13 - .../shape_get_pokemon_species.rs | 136 -- .../shape_get_pokemon_species_input.rs | 12 - .../shape_get_pokemon_species_output.rs | 35 - .../shape_get_server_statistics.rs | 55 - .../shape_get_server_statistics_output.rs | 23 - .../src/protocol_serde/shape_get_storage.rs | 163 -- .../protocol_serde/shape_get_storage_input.rs | 22 - .../shape_get_storage_output.rs | 29 - .../shape_invalid_pokeball_error.rs | 23 - .../shape_master_ball_unsuccessful.rs | 72 - .../shape_resource_not_found_exception.rs | 23 - .../shape_storage_access_not_authorized.rs | 20 - .../shape_stream_pokemon_radio.rs | 51 - .../shape_stream_pokemon_radio_output.rs | 9 - .../protocol_serde/shape_throttling_error.rs | 17 - .../shape_unsupported_region_error.rs | 23 - .../shape_validation_exception.rs | 35 - .../shape_validation_exception_field.rs | 13 - .../src/service.rs | 1963 ----------------- .../src/types.rs | 13 - examples/upgrade-http1x.md | 317 +-- 40 files changed, 6 insertions(+), 7689 deletions(-) delete mode 100644 examples/pokemon-service-server-skd-patch/Cargo.toml delete mode 100644 examples/pokemon-service-server-skd-patch/src/constrained.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/error.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/hyper_compat.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/input.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/lib.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/model.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/operation.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/operation_shape.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/service.rs delete mode 100644 examples/pokemon-service-server-skd-patch/src/types.rs diff --git a/examples/pokemon-service-server-skd-patch/Cargo.toml b/examples/pokemon-service-server-skd-patch/Cargo.toml deleted file mode 100644 index f68546b8ebe..00000000000 --- a/examples/pokemon-service-server-skd-patch/Cargo.toml +++ /dev/null @@ -1,63 +0,0 @@ -# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -[package] -name = "pokemon-service-server-sdk" -version = "0.0.1" -authors = ["protocoltest@example.com"] -description = "test" -edition = "2021" - -[package.metadata.smithy] -codegen-version = "d4ac0215345535bd30b0e19b5b33ea4de8b1528c" -[dependencies.aws-smithy-eventstream] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-eventstream" -[dependencies.aws-smithy-http] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-http" -features = ["event-stream"] -[dependencies.aws-smithy-http-server] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-http-server" -[dependencies.aws-smithy-json] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-json" -[dependencies.aws-smithy-runtime-api] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-runtime-api" -features = ["http-1x"] -[dependencies.aws-smithy-types] -path = "/Volumes/workplace/upgrade-http/server/rust-runtime/aws-smithy-types" -features = ["http-body-1-x"] -[dependencies.futures-util] -version = "0.3" -[dependencies.http] -version = "1" -[dependencies.mime] -version = "0.3" -[dependencies.nom] -version = "7" -[dependencies.percent-encoding] -version = "2.0.0" -[dependencies.pin-project-lite] -version = "0.2" -[dependencies.tower] -version = "0.4" -[dependencies.bytes] -version = "1" -[dependencies.http-body-1-0] -package = "http-body" -version = "1" -[dependencies.tracing] -version = "0.1" -# TODO: PATCH - http-body already exists as http-body-1-0, bytes already exists, hyper added for compatibility -[dependencies.hyper] -version = "1" -[dev-dependencies.hyper] -version = "1" -[dev-dependencies.hyper-util] -version = "0.1" -features = ["service"] -[dev-dependencies.tokio] -version = "1.23.1" -[features] -aws-lambda = ["aws-smithy-http-server/aws-lambda"] -request-id = ["aws-smithy-http-server/request-id"] -rt-tokio = ["aws-smithy-types/http-body-1-x", "aws-smithy-types/rt-tokio"] -default = ["request-id", "rt-tokio"] - - diff --git a/examples/pokemon-service-server-skd-patch/src/constrained.rs b/examples/pokemon-service-server-skd-patch/src/constrained.rs deleted file mode 100644 index b5f7300bd71..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/constrained.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0 - */ - -pub(crate) trait Constrained { - type Unconstrained; -} - -#[derive(Debug, Clone)] -#[allow(dead_code)] -pub(crate) enum MaybeConstrained { - Constrained(T), - Unconstrained(T::Unconstrained), -} diff --git a/examples/pokemon-service-server-skd-patch/src/error.rs b/examples/pokemon-service-server-skd-patch/src/error.rs deleted file mode 100644 index 263b4038eee..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/error.rs +++ /dev/null @@ -1,885 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -/// Error type for the `GetStorage` operation. -/// Each variant represents an error that can occur for the `GetStorage` operation. -#[derive(::std::fmt::Debug)] -pub enum GetStorageError { - #[allow(missing_docs)] // documentation missing in model - ResourceNotFoundException(crate::error::ResourceNotFoundException), - /// Not authorized to access Pokémon storage. - StorageAccessNotAuthorized(crate::error::StorageAccessNotAuthorized), - /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. - ValidationException(crate::error::ValidationException), -} -impl ::std::fmt::Display for GetStorageError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - GetStorageError::ResourceNotFoundException(_inner) => _inner.fmt(f), - GetStorageError::StorageAccessNotAuthorized(_inner) => _inner.fmt(f), - GetStorageError::ValidationException(_inner) => _inner.fmt(f), - } - } -} -impl GetStorageError { - /// Returns `true` if the error kind is `GetStorageError::ResourceNotFoundException`. - pub fn is_resource_not_found_exception(&self) -> bool { - matches!(&self, GetStorageError::ResourceNotFoundException(_)) - } - /// Returns `true` if the error kind is `GetStorageError::StorageAccessNotAuthorized`. - pub fn is_storage_access_not_authorized(&self) -> bool { - matches!(&self, GetStorageError::StorageAccessNotAuthorized(_)) - } - /// Returns `true` if the error kind is `GetStorageError::ValidationException`. - pub fn is_validation_exception(&self) -> bool { - matches!(&self, GetStorageError::ValidationException(_)) - } - /// Returns the error name string by matching the correct variant. - pub fn name(&self) -> &'static str { - match &self { - GetStorageError::ResourceNotFoundException(_inner) => _inner.name(), - GetStorageError::StorageAccessNotAuthorized(_inner) => _inner.name(), - GetStorageError::ValidationException(_inner) => _inner.name(), - } - } -} -impl ::std::error::Error for GetStorageError { - fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { - match &self { - GetStorageError::ResourceNotFoundException(_inner) => Some(_inner), - GetStorageError::StorageAccessNotAuthorized(_inner) => Some(_inner), - GetStorageError::ValidationException(_inner) => Some(_inner), - } - } -} -impl ::std::convert::From - for crate::error::GetStorageError -{ - fn from(variant: crate::error::ResourceNotFoundException) -> crate::error::GetStorageError { - Self::ResourceNotFoundException(variant) - } -} -impl ::std::convert::From - for crate::error::GetStorageError -{ - fn from(variant: crate::error::StorageAccessNotAuthorized) -> crate::error::GetStorageError { - Self::StorageAccessNotAuthorized(variant) - } -} -impl ::std::convert::From for crate::error::GetStorageError { - fn from(variant: crate::error::ValidationException) -> crate::error::GetStorageError { - Self::ValidationException(variant) - } -} - -/// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct ValidationException { - /// A summary of the validation failure. - pub message: ::std::string::String, - /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. - pub field_list: ::std::option::Option<::std::vec::Vec>, -} -impl ValidationException { - /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. - pub fn field_list(&self) -> ::std::option::Option<&[crate::model::ValidationExceptionField]> { - self.field_list.as_deref() - } -} -impl ValidationException { - /// Returns the error message. - pub fn message(&self) -> &str { - &self.message - } - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "ValidationException" - } -} -impl ::std::fmt::Display for ValidationException { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "ValidationException")?; - { - ::std::write!(f, ": {}", &self.message)?; - } - Ok(()) - } -} -impl ::std::error::Error for ValidationException {} -impl ValidationException { - /// Creates a new builder-style object to manufacture [`ValidationException`](crate::error::ValidationException). - pub fn builder() -> crate::error::validation_exception::Builder { - crate::error::validation_exception::Builder::default() - } -} - -/// Not authorized to access Pokémon storage. -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct StorageAccessNotAuthorized {} -impl StorageAccessNotAuthorized { - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "StorageAccessNotAuthorized" - } -} -impl ::std::fmt::Display for StorageAccessNotAuthorized { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "StorageAccessNotAuthorized")?; - Ok(()) - } -} -impl ::std::error::Error for StorageAccessNotAuthorized {} -impl StorageAccessNotAuthorized { - /// Creates a new builder-style object to manufacture [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). - pub fn builder() -> crate::error::storage_access_not_authorized::Builder { - crate::error::storage_access_not_authorized::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct ResourceNotFoundException { - #[allow(missing_docs)] // documentation missing in model - pub message: ::std::string::String, -} -impl ResourceNotFoundException { - /// Returns the error message. - pub fn message(&self) -> &str { - &self.message - } - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "ResourceNotFoundException" - } -} -impl ::std::fmt::Display for ResourceNotFoundException { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "ResourceNotFoundException")?; - { - ::std::write!(f, ": {}", &self.message)?; - } - Ok(()) - } -} -impl ::std::error::Error for ResourceNotFoundException {} -impl ResourceNotFoundException { - /// Creates a new builder-style object to manufacture [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). - pub fn builder() -> crate::error::resource_not_found_exception::Builder { - crate::error::resource_not_found_exception::Builder::default() - } -} - -/// Error type for the `GetPokemonSpecies` operation. -/// Each variant represents an error that can occur for the `GetPokemonSpecies` operation. -#[derive(::std::fmt::Debug)] -pub enum GetPokemonSpeciesError { - #[allow(missing_docs)] // documentation missing in model - ResourceNotFoundException(crate::error::ResourceNotFoundException), - /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. - ValidationException(crate::error::ValidationException), -} -impl ::std::fmt::Display for GetPokemonSpeciesError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - GetPokemonSpeciesError::ResourceNotFoundException(_inner) => _inner.fmt(f), - GetPokemonSpeciesError::ValidationException(_inner) => _inner.fmt(f), - } - } -} -impl GetPokemonSpeciesError { - /// Returns `true` if the error kind is `GetPokemonSpeciesError::ResourceNotFoundException`. - pub fn is_resource_not_found_exception(&self) -> bool { - matches!(&self, GetPokemonSpeciesError::ResourceNotFoundException(_)) - } - /// Returns `true` if the error kind is `GetPokemonSpeciesError::ValidationException`. - pub fn is_validation_exception(&self) -> bool { - matches!(&self, GetPokemonSpeciesError::ValidationException(_)) - } - /// Returns the error name string by matching the correct variant. - pub fn name(&self) -> &'static str { - match &self { - GetPokemonSpeciesError::ResourceNotFoundException(_inner) => _inner.name(), - GetPokemonSpeciesError::ValidationException(_inner) => _inner.name(), - } - } -} -impl ::std::error::Error for GetPokemonSpeciesError { - fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { - match &self { - GetPokemonSpeciesError::ResourceNotFoundException(_inner) => Some(_inner), - GetPokemonSpeciesError::ValidationException(_inner) => Some(_inner), - } - } -} -impl ::std::convert::From - for crate::error::GetPokemonSpeciesError -{ - fn from( - variant: crate::error::ResourceNotFoundException, - ) -> crate::error::GetPokemonSpeciesError { - Self::ResourceNotFoundException(variant) - } -} -impl ::std::convert::From - for crate::error::GetPokemonSpeciesError -{ - fn from(variant: crate::error::ValidationException) -> crate::error::GetPokemonSpeciesError { - Self::ValidationException(variant) - } -} - -/// Error type for the `CapturePokemon` operation. -/// Each variant represents an error that can occur for the `CapturePokemon` operation. -#[derive(::std::fmt::Debug)] -pub enum CapturePokemonError { - #[allow(missing_docs)] // documentation missing in model - UnsupportedRegionError(crate::error::UnsupportedRegionError), - #[allow(missing_docs)] // documentation missing in model - ThrottlingError(crate::error::ThrottlingError), - /// A standard error for input validation failures. This should be thrown by services when a member of the input structure falls outside of the modeled or documented constraints. - ValidationException(crate::error::ValidationException), - #[allow(missing_docs)] // documentation missing in model - MasterBallUnsuccessful(crate::error::MasterBallUnsuccessful), - #[allow(missing_docs)] // documentation missing in model - InvalidPokeballError(crate::error::InvalidPokeballError), -} -impl ::std::fmt::Display for CapturePokemonError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - CapturePokemonError::UnsupportedRegionError(_inner) => _inner.fmt(f), - CapturePokemonError::ThrottlingError(_inner) => _inner.fmt(f), - CapturePokemonError::ValidationException(_inner) => _inner.fmt(f), - CapturePokemonError::MasterBallUnsuccessful(_inner) => _inner.fmt(f), - CapturePokemonError::InvalidPokeballError(_inner) => _inner.fmt(f), - } - } -} -impl CapturePokemonError { - /// Returns `true` if the error kind is `CapturePokemonError::UnsupportedRegionError`. - pub fn is_unsupported_region_error(&self) -> bool { - matches!(&self, CapturePokemonError::UnsupportedRegionError(_)) - } - /// Returns `true` if the error kind is `CapturePokemonError::ThrottlingError`. - pub fn is_throttling_error(&self) -> bool { - matches!(&self, CapturePokemonError::ThrottlingError(_)) - } - /// Returns `true` if the error kind is `CapturePokemonError::ValidationException`. - pub fn is_validation_exception(&self) -> bool { - matches!(&self, CapturePokemonError::ValidationException(_)) - } - /// Returns `true` if the error kind is `CapturePokemonError::MasterBallUnsuccessful`. - pub fn is_master_ball_unsuccessful(&self) -> bool { - matches!(&self, CapturePokemonError::MasterBallUnsuccessful(_)) - } - /// Returns `true` if the error kind is `CapturePokemonError::InvalidPokeballError`. - pub fn is_invalid_pokeball_error(&self) -> bool { - matches!(&self, CapturePokemonError::InvalidPokeballError(_)) - } - /// Returns the error name string by matching the correct variant. - pub fn name(&self) -> &'static str { - match &self { - CapturePokemonError::UnsupportedRegionError(_inner) => _inner.name(), - CapturePokemonError::ThrottlingError(_inner) => _inner.name(), - CapturePokemonError::ValidationException(_inner) => _inner.name(), - CapturePokemonError::MasterBallUnsuccessful(_inner) => _inner.name(), - CapturePokemonError::InvalidPokeballError(_inner) => _inner.name(), - } - } -} -impl ::std::error::Error for CapturePokemonError { - fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { - match &self { - CapturePokemonError::UnsupportedRegionError(_inner) => Some(_inner), - CapturePokemonError::ThrottlingError(_inner) => Some(_inner), - CapturePokemonError::ValidationException(_inner) => Some(_inner), - CapturePokemonError::MasterBallUnsuccessful(_inner) => Some(_inner), - CapturePokemonError::InvalidPokeballError(_inner) => Some(_inner), - } - } -} -impl ::std::convert::From - for crate::error::CapturePokemonError -{ - fn from(variant: crate::error::UnsupportedRegionError) -> crate::error::CapturePokemonError { - Self::UnsupportedRegionError(variant) - } -} -impl ::std::convert::From for crate::error::CapturePokemonError { - fn from(variant: crate::error::ThrottlingError) -> crate::error::CapturePokemonError { - Self::ThrottlingError(variant) - } -} -impl ::std::convert::From for crate::error::CapturePokemonError { - fn from(variant: crate::error::ValidationException) -> crate::error::CapturePokemonError { - Self::ValidationException(variant) - } -} -impl ::std::convert::From - for crate::error::CapturePokemonError -{ - fn from(variant: crate::error::MasterBallUnsuccessful) -> crate::error::CapturePokemonError { - Self::MasterBallUnsuccessful(variant) - } -} -impl ::std::convert::From - for crate::error::CapturePokemonError -{ - fn from(variant: crate::error::InvalidPokeballError) -> crate::error::CapturePokemonError { - Self::InvalidPokeballError(variant) - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct InvalidPokeballError { - #[allow(missing_docs)] // documentation missing in model - pub pokeball: ::std::string::String, -} -impl InvalidPokeballError { - #[allow(missing_docs)] // documentation missing in model - pub fn pokeball(&self) -> &str { - use std::ops::Deref; - self.pokeball.deref() - } -} -impl InvalidPokeballError { - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "InvalidPokeballError" - } -} -impl ::std::fmt::Display for InvalidPokeballError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "InvalidPokeballError")?; - Ok(()) - } -} -impl ::std::error::Error for InvalidPokeballError {} -impl InvalidPokeballError { - /// Creates a new builder-style object to manufacture [`InvalidPokeballError`](crate::error::InvalidPokeballError). - pub fn builder() -> crate::error::invalid_pokeball_error::Builder { - crate::error::invalid_pokeball_error::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct MasterBallUnsuccessful { - #[allow(missing_docs)] // documentation missing in model - pub message: ::std::option::Option<::std::string::String>, -} -impl MasterBallUnsuccessful { - /// Returns the error message. - pub fn message(&self) -> ::std::option::Option<&str> { - self.message.as_deref() - } - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "MasterBallUnsuccessful" - } -} -impl ::std::fmt::Display for MasterBallUnsuccessful { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "MasterBallUnsuccessful")?; - if let ::std::option::Option::Some(inner_1) = &self.message { - { - ::std::write!(f, ": {}", inner_1)?; - } - } - Ok(()) - } -} -impl ::std::error::Error for MasterBallUnsuccessful {} -impl MasterBallUnsuccessful { - /// Creates a new builder-style object to manufacture [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). - pub fn builder() -> crate::error::master_ball_unsuccessful::Builder { - crate::error::master_ball_unsuccessful::Builder::default() - } -} -impl crate::constrained::Constrained for crate::error::MasterBallUnsuccessful { - type Unconstrained = crate::error::master_ball_unsuccessful::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct ThrottlingError {} -impl ThrottlingError { - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "ThrottlingError" - } -} -impl ::std::fmt::Display for ThrottlingError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "ThrottlingError")?; - Ok(()) - } -} -impl ::std::error::Error for ThrottlingError {} -impl ThrottlingError { - /// Creates a new builder-style object to manufacture [`ThrottlingError`](crate::error::ThrottlingError). - pub fn builder() -> crate::error::throttling_error::Builder { - crate::error::throttling_error::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct UnsupportedRegionError { - #[allow(missing_docs)] // documentation missing in model - pub region: ::std::string::String, -} -impl UnsupportedRegionError { - #[allow(missing_docs)] // documentation missing in model - pub fn region(&self) -> &str { - use std::ops::Deref; - self.region.deref() - } -} -impl UnsupportedRegionError { - #[doc(hidden)] - /// Returns the error name. - pub fn name(&self) -> &'static str { - "UnsupportedRegionError" - } -} -impl ::std::fmt::Display for UnsupportedRegionError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - ::std::write!(f, "UnsupportedRegionError")?; - Ok(()) - } -} -impl ::std::error::Error for UnsupportedRegionError {} -impl UnsupportedRegionError { - /// Creates a new builder-style object to manufacture [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). - pub fn builder() -> crate::error::unsupported_region_error::Builder { - crate::error::unsupported_region_error::Builder::default() - } -} - -/// Error type for the `CapturePokemonEvents` operation. -/// Each variant represents an error that can occur for the `CapturePokemonEvents` operation. -#[derive(::std::fmt::Debug)] -pub enum CapturePokemonEventsError { - #[allow(missing_docs)] // documentation missing in model - InvalidPokeballError(crate::error::InvalidPokeballError), - #[allow(missing_docs)] // documentation missing in model - ThrottlingError(crate::error::ThrottlingError), -} -impl ::std::fmt::Display for CapturePokemonEventsError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - CapturePokemonEventsError::InvalidPokeballError(_inner) => _inner.fmt(f), - CapturePokemonEventsError::ThrottlingError(_inner) => _inner.fmt(f), - } - } -} -impl CapturePokemonEventsError { - /// Returns `true` if the error kind is `CapturePokemonEventsError::InvalidPokeballError`. - pub fn is_invalid_pokeball_error(&self) -> bool { - matches!(&self, CapturePokemonEventsError::InvalidPokeballError(_)) - } - /// Returns `true` if the error kind is `CapturePokemonEventsError::ThrottlingError`. - pub fn is_throttling_error(&self) -> bool { - matches!(&self, CapturePokemonEventsError::ThrottlingError(_)) - } - /// Returns the error name string by matching the correct variant. - pub fn name(&self) -> &'static str { - match &self { - CapturePokemonEventsError::InvalidPokeballError(_inner) => _inner.name(), - CapturePokemonEventsError::ThrottlingError(_inner) => _inner.name(), - } - } -} -impl ::std::error::Error for CapturePokemonEventsError { - fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { - match &self { - CapturePokemonEventsError::InvalidPokeballError(_inner) => Some(_inner), - CapturePokemonEventsError::ThrottlingError(_inner) => Some(_inner), - } - } -} -impl ::std::convert::From - for crate::error::CapturePokemonEventsError -{ - fn from( - variant: crate::error::InvalidPokeballError, - ) -> crate::error::CapturePokemonEventsError { - Self::InvalidPokeballError(variant) - } -} -impl ::std::convert::From - for crate::error::CapturePokemonEventsError -{ - fn from(variant: crate::error::ThrottlingError) -> crate::error::CapturePokemonEventsError { - Self::ThrottlingError(variant) - } -} - -/// Error type for the `AttemptCapturingPokemonEvent` operation. -/// Each variant represents an error that can occur for the `AttemptCapturingPokemonEvent` operation. -#[derive(::std::fmt::Debug)] -pub enum AttemptCapturingPokemonEventError { - #[allow(missing_docs)] // documentation missing in model - MasterBallUnsuccessful(crate::error::MasterBallUnsuccessful), -} -impl ::std::fmt::Display for AttemptCapturingPokemonEventError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match &self { - AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => _inner.fmt(f), - } - } -} -impl AttemptCapturingPokemonEventError { - /// Returns `true` if the error kind is `AttemptCapturingPokemonEventError::MasterBallUnsuccessful`. - pub fn is_master_ball_unsuccessful(&self) -> bool { - matches!( - &self, - AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_) - ) - } - /// Returns the error name string by matching the correct variant. - pub fn name(&self) -> &'static str { - match &self { - AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => _inner.name(), - } - } -} -impl ::std::error::Error for AttemptCapturingPokemonEventError { - fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> { - match &self { - AttemptCapturingPokemonEventError::MasterBallUnsuccessful(_inner) => Some(_inner), - } - } -} -impl ::std::convert::From - for crate::error::AttemptCapturingPokemonEventError -{ - fn from( - variant: crate::error::MasterBallUnsuccessful, - ) -> crate::error::AttemptCapturingPokemonEventError { - Self::MasterBallUnsuccessful(variant) - } -} - -/// See [`ValidationException`](crate::error::ValidationException). -pub mod validation_exception { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `message` was not provided but it is required when building `ValidationException`. - MissingMessage, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ValidationException`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::error::ValidationException { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`ValidationException`](crate::error::ValidationException). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) message: ::std::option::Option<::std::string::String>, - pub(crate) field_list: - ::std::option::Option<::std::vec::Vec>, - } - impl Builder { - /// A summary of the validation failure. - pub fn message(mut self, input: ::std::string::String) -> Self { - self.message = Some(input); - self - } - /// A list of specific failures encountered while validating the input. A member can appear in this list more than once if it failed to satisfy multiple constraints. - pub fn field_list( - mut self, - input: ::std::option::Option<::std::vec::Vec>, - ) -> Self { - self.field_list = input; - self - } - /// Consumes the builder and constructs a [`ValidationException`](crate::error::ValidationException). - /// - /// The builder fails to construct a [`ValidationException`](crate::error::ValidationException) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::error::ValidationException { - message: self.message.ok_or(ConstraintViolation::MissingMessage)?, - field_list: self.field_list, - }) - } - } -} -/// See [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). -pub mod storage_access_not_authorized { - - impl ::std::convert::From for crate::error::StorageAccessNotAuthorized { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`StorageAccessNotAuthorized`](crate::error::StorageAccessNotAuthorized). - pub fn build(self) -> crate::error::StorageAccessNotAuthorized { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::error::StorageAccessNotAuthorized { - crate::error::StorageAccessNotAuthorized {} - } - } -} -/// See [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). -pub mod resource_not_found_exception { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `message` was not provided but it is required when building `ResourceNotFoundException`. - MissingMessage, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ResourceNotFoundException`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::error::ResourceNotFoundException { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) message: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn message(mut self, input: ::std::string::String) -> Self { - self.message = Some(input); - self - } - /// Consumes the builder and constructs a [`ResourceNotFoundException`](crate::error::ResourceNotFoundException). - /// - /// The builder fails to construct a [`ResourceNotFoundException`](crate::error::ResourceNotFoundException) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::error::ResourceNotFoundException { - message: self.message.ok_or(ConstraintViolation::MissingMessage)?, - }) - } - } -} -/// See [`InvalidPokeballError`](crate::error::InvalidPokeballError). -pub mod invalid_pokeball_error { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `pokeball` was not provided but it is required when building `InvalidPokeballError`. - MissingPokeball, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingPokeball => write!(f, "`pokeball` was not provided but it is required when building `InvalidPokeballError`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::error::InvalidPokeballError { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`InvalidPokeballError`](crate::error::InvalidPokeballError). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) pokeball: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn pokeball(mut self, input: ::std::string::String) -> Self { - self.pokeball = Some(input); - self - } - /// Consumes the builder and constructs a [`InvalidPokeballError`](crate::error::InvalidPokeballError). - /// - /// The builder fails to construct a [`InvalidPokeballError`](crate::error::InvalidPokeballError) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::error::InvalidPokeballError { - pokeball: self.pokeball.ok_or(ConstraintViolation::MissingPokeball)?, - }) - } - } -} -/// See [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). -pub mod master_ball_unsuccessful { - - impl ::std::convert::From for crate::error::MasterBallUnsuccessful { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) message: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn message(mut self, input: ::std::option::Option<::std::string::String>) -> Self { - self.message = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_message( - mut self, - input: Option>, - ) -> Self { - self.message = input.map(|v| v.into()); - self - } - /// Consumes the builder and constructs a [`MasterBallUnsuccessful`](crate::error::MasterBallUnsuccessful). - pub fn build(self) -> crate::error::MasterBallUnsuccessful { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::error::MasterBallUnsuccessful { - crate::error::MasterBallUnsuccessful { - message: self.message, - } - } - } -} -/// See [`ThrottlingError`](crate::error::ThrottlingError). -pub mod throttling_error { - - impl ::std::convert::From for crate::error::ThrottlingError { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`ThrottlingError`](crate::error::ThrottlingError). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`ThrottlingError`](crate::error::ThrottlingError). - pub fn build(self) -> crate::error::ThrottlingError { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::error::ThrottlingError { - crate::error::ThrottlingError {} - } - } -} -/// See [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). -pub mod unsupported_region_error { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `region` was not provided but it is required when building `UnsupportedRegionError`. - MissingRegion, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingRegion => write!(f, "`region` was not provided but it is required when building `UnsupportedRegionError`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::error::UnsupportedRegionError { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) region: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn region(mut self, input: ::std::string::String) -> Self { - self.region = Some(input); - self - } - /// Consumes the builder and constructs a [`UnsupportedRegionError`](crate::error::UnsupportedRegionError). - /// - /// The builder fails to construct a [`UnsupportedRegionError`](crate::error::UnsupportedRegionError) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::error::UnsupportedRegionError { - region: self.region.ok_or(ConstraintViolation::MissingRegion)?, - }) - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs b/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs deleted file mode 100644 index 3d8b5631a04..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/event_stream_serde.rs +++ /dev/null @@ -1,202 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[non_exhaustive] -#[derive(Debug)] -pub struct CapturePokemonEventsErrorMarshaller; - -impl CapturePokemonEventsErrorMarshaller { - pub fn new() -> Self { - CapturePokemonEventsErrorMarshaller - } -} -impl ::aws_smithy_eventstream::frame::MarshallMessage for CapturePokemonEventsErrorMarshaller { - type Input = crate::error::CapturePokemonEventsError; - fn marshall( - &self, - _input: Self::Input, - ) -> std::result::Result< - ::aws_smithy_types::event_stream::Message, - ::aws_smithy_eventstream::error::Error, - > { - let mut headers = Vec::new(); - headers.push(::aws_smithy_types::event_stream::Header::new( - ":message-type", - ::aws_smithy_types::event_stream::HeaderValue::String("exception".into()), - )); - let payload = match _input { - crate::error::CapturePokemonEventsError::InvalidPokeballError(inner) => { - headers.push(::aws_smithy_types::event_stream::Header::new( - ":exception-type", - ::aws_smithy_types::event_stream::HeaderValue::String( - "invalid_pokeball".into(), - ), - )); - headers.push(::aws_smithy_types::event_stream::Header::new( - ":content-type", - ::aws_smithy_types::event_stream::HeaderValue::String( - "application/json".into(), - ), - )); - crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error_error(&inner) - .map_err(|err| ::aws_smithy_eventstream::error::Error::marshalling(format!("{}", err)))? - } - crate::error::CapturePokemonEventsError::ThrottlingError(inner) => { - headers.push(::aws_smithy_types::event_stream::Header::new( - ":exception-type", - ::aws_smithy_types::event_stream::HeaderValue::String("throttlingError".into()), - )); - headers.push(::aws_smithy_types::event_stream::Header::new( - ":content-type", - ::aws_smithy_types::event_stream::HeaderValue::String( - "application/json".into(), - ), - )); - crate::protocol_serde::shape_throttling_error::ser_throttling_error_error(&inner) - .map_err(|err| { - ::aws_smithy_eventstream::error::Error::marshalling(format!("{}", err)) - })? - } - }; - Ok(::aws_smithy_types::event_stream::Message::new_from_parts( - headers, payload, - )) - } -} - -#[non_exhaustive] -#[derive(Debug)] -pub struct CapturePokemonEventsMarshaller; - -impl CapturePokemonEventsMarshaller { - pub fn new() -> Self { - CapturePokemonEventsMarshaller - } -} -impl ::aws_smithy_eventstream::frame::MarshallMessage for CapturePokemonEventsMarshaller { - type Input = crate::model::CapturePokemonEvents; - fn marshall( - &self, - input: Self::Input, - ) -> std::result::Result< - ::aws_smithy_types::event_stream::Message, - ::aws_smithy_eventstream::error::Error, - > { - let mut headers = Vec::new(); - headers.push(::aws_smithy_types::event_stream::Header::new( - ":message-type", - ::aws_smithy_types::event_stream::HeaderValue::String("event".into()), - )); - let payload = match input { - Self::Input::Event(inner) => { - headers.push(::aws_smithy_types::event_stream::Header::new( - ":event-type", - ::aws_smithy_types::event_stream::HeaderValue::String("event".into()), - )); - if let Some(value) = inner.name { - headers.push(::aws_smithy_types::event_stream::Header::new( - "name", - ::aws_smithy_types::event_stream::HeaderValue::String(value.into()), - )); - } - if let Some(value) = inner.captured { - headers.push(::aws_smithy_types::event_stream::Header::new( - "captured", - ::aws_smithy_types::event_stream::HeaderValue::Bool(value), - )); - } - if let Some(value) = inner.shiny { - headers.push(::aws_smithy_types::event_stream::Header::new( - "shiny", - ::aws_smithy_types::event_stream::HeaderValue::Bool(value), - )); - } - headers.push(::aws_smithy_types::event_stream::Header::new( - ":content-type", - ::aws_smithy_types::event_stream::HeaderValue::String( - "application/octet-stream".into(), - ), - )); - if let Some(inner_payload) = inner.pokedex_update { - inner_payload.into_inner() - } else { - Vec::new() - } - } - }; - Ok(::aws_smithy_types::event_stream::Message::new_from_parts( - headers, payload, - )) - } -} - -#[non_exhaustive] -#[derive(Debug)] -pub struct AttemptCapturingPokemonEventUnmarshaller; - -impl AttemptCapturingPokemonEventUnmarshaller { - pub fn new() -> Self { - AttemptCapturingPokemonEventUnmarshaller - } -} -impl ::aws_smithy_eventstream::frame::UnmarshallMessage - for AttemptCapturingPokemonEventUnmarshaller -{ - type Output = crate::model::AttemptCapturingPokemonEvent; - type Error = crate::error::AttemptCapturingPokemonEventError; - fn unmarshall( - &self, - message: &::aws_smithy_types::event_stream::Message, - ) -> std::result::Result< - ::aws_smithy_eventstream::frame::UnmarshalledMessage, - ::aws_smithy_eventstream::error::Error, - > { - let response_headers = ::aws_smithy_eventstream::smithy::parse_response_headers(message)?; - match response_headers.message_type.as_str() { - "event" => match response_headers.smithy_type.as_str() { - "event" => { - let mut builder = crate::model::capturing_event::Builder::default(); - builder = builder.set_payload( - Some( - crate::protocol_serde::shape_capturing_payload::de_capturing_payload_payload(&message.payload()[..]) - .map_err(|err| { - ::aws_smithy_eventstream::error::Error::unmarshalling(format!("failed to unmarshall payload: {}", err)) - })? - ) - ); - Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Event( - crate::model::AttemptCapturingPokemonEvent::Event(builder.build()), - )) - } - _unknown_variant => { - return Err(::aws_smithy_eventstream::error::Error::unmarshalling( - format!("unrecognized :event-type: {}", _unknown_variant), - )); - } - }, - "exception" => { - if response_headers.smithy_type.as_str() == "masterball_unsuccessful" { - let mut builder = crate::error::master_ball_unsuccessful::Builder::default(); - builder = crate::protocol_serde::shape_master_ball_unsuccessful::de_master_ball_unsuccessful_json_err(&message.payload()[..], builder) - .map_err(|err| { - ::aws_smithy_eventstream::error::Error::unmarshalling(format!("failed to unmarshall masterball_unsuccessful: {}", err)) - })?; - return Ok(::aws_smithy_eventstream::frame::UnmarshalledMessage::Error( - crate::error::AttemptCapturingPokemonEventError::MasterBallUnsuccessful( - builder.build(), - ), - )); - } - return Err(aws_smithy_eventstream::error::Error::unmarshalling( - format!( - "unrecognized exception: {}", - response_headers.smithy_type.as_str() - ), - )); - } - value => { - return Err(::aws_smithy_eventstream::error::Error::unmarshalling( - format!("unrecognized :message-type: {}", value), - )); - } - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs b/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs deleted file mode 100644 index a576bb28deb..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/hyper_compat.rs +++ /dev/null @@ -1,27 +0,0 @@ -// TODO: PATCH - Hyper 1.x compatibility module - -use crate::types::ByteStream; - -// Newtype wrapper to work around orphan rules -#[derive(Debug)] -pub struct HyperIncoming(pub hyper::body::Incoming); - -impl From for ByteStream { - fn from(wrapper: HyperIncoming) -> Self { - ByteStream::from_body_1_x(wrapper.0) - } -} - -impl From for HyperIncoming { - fn from(body: hyper::body::Incoming) -> Self { - HyperIncoming(body) - } -} - -// Provide a blanket implementation for hyper::body::Incoming -> ByteStream -// by going through our newtype -impl From for ByteStream { - fn from(body: hyper::body::Incoming) -> Self { - HyperIncoming::from(body).into() - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/input.rs b/examples/pokemon-service-server-skd-patch/src/input.rs deleted file mode 100644 index f6d3ba07afe..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/input.rs +++ /dev/null @@ -1,618 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. - -/// A request to access Pokémon storage. -#[derive(::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::hash::Hash)] -pub struct GetStorageInput { - #[allow(missing_docs)] // documentation missing in model - pub user: ::std::string::String, - #[allow(missing_docs)] // documentation missing in model - pub passcode: ::std::string::String, -} -impl GetStorageInput { - #[allow(missing_docs)] // documentation missing in model - pub fn user(&self) -> &str { - use std::ops::Deref; - self.user.deref() - } - #[allow(missing_docs)] // documentation missing in model - pub fn passcode(&self) -> &str { - use std::ops::Deref; - self.passcode.deref() - } -} -impl ::std::fmt::Debug for GetStorageInput { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - let mut formatter = f.debug_struct("GetStorageInput"); - formatter.field("user", &"*** Sensitive Data Redacted ***"); - formatter.field("passcode", &"*** Sensitive Data Redacted ***"); - formatter.finish() - } -} -impl GetStorageInput { - /// Creates a new builder-style object to manufacture [`GetStorageInput`](crate::input::GetStorageInput). - pub fn builder() -> crate::input::get_storage_input::Builder { - crate::input::get_storage_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::GetStorageInput { - type Unconstrained = crate::input::get_storage_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct GetPokemonSpeciesInput { - #[allow(missing_docs)] // documentation missing in model - pub name: ::std::string::String, -} -impl GetPokemonSpeciesInput { - #[allow(missing_docs)] // documentation missing in model - pub fn name(&self) -> &str { - use std::ops::Deref; - self.name.deref() - } -} -impl GetPokemonSpeciesInput { - /// Creates a new builder-style object to manufacture [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). - pub fn builder() -> crate::input::get_pokemon_species_input::Builder { - crate::input::get_pokemon_species_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::GetPokemonSpeciesInput { - type Unconstrained = crate::input::get_pokemon_species_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct StreamPokemonRadioInput {} -impl StreamPokemonRadioInput { - /// Creates a new builder-style object to manufacture [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). - pub fn builder() -> crate::input::stream_pokemon_radio_input::Builder { - crate::input::stream_pokemon_radio_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::StreamPokemonRadioInput { - type Unconstrained = crate::input::stream_pokemon_radio_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct CheckHealthInput {} -impl CheckHealthInput { - /// Creates a new builder-style object to manufacture [`CheckHealthInput`](crate::input::CheckHealthInput). - pub fn builder() -> crate::input::check_health_input::Builder { - crate::input::check_health_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::CheckHealthInput { - type Unconstrained = crate::input::check_health_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive(::std::fmt::Debug)] -pub struct CapturePokemonInput { - #[allow(missing_docs)] // documentation missing in model - pub events: ::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - >, - #[allow(missing_docs)] // documentation missing in model - pub region: ::std::string::String, -} -impl CapturePokemonInput { - #[allow(missing_docs)] // documentation missing in model - pub fn events( - &self, - ) -> &::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - > { - &self.events - } - #[allow(missing_docs)] // documentation missing in model - pub fn region(&self) -> &str { - use std::ops::Deref; - self.region.deref() - } -} -impl CapturePokemonInput { - /// Creates a new builder-style object to manufacture [`CapturePokemonInput`](crate::input::CapturePokemonInput). - pub fn builder() -> crate::input::capture_pokemon_input::Builder { - crate::input::capture_pokemon_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::CapturePokemonInput { - type Unconstrained = crate::input::capture_pokemon_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct DoNothingInput {} -impl DoNothingInput { - /// Creates a new builder-style object to manufacture [`DoNothingInput`](crate::input::DoNothingInput). - pub fn builder() -> crate::input::do_nothing_input::Builder { - crate::input::do_nothing_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::DoNothingInput { - type Unconstrained = crate::input::do_nothing_input::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct GetServerStatisticsInput {} -impl GetServerStatisticsInput { - /// Creates a new builder-style object to manufacture [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). - pub fn builder() -> crate::input::get_server_statistics_input::Builder { - crate::input::get_server_statistics_input::Builder::default() - } -} -impl crate::constrained::Constrained for crate::input::GetServerStatisticsInput { - type Unconstrained = crate::input::get_server_statistics_input::Builder; -} -/// See [`GetStorageInput`](crate::input::GetStorageInput). -pub mod get_storage_input { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `user` was not provided but it is required when building `GetStorageInput`. - MissingUser, - /// `passcode` was not provided but it is required when building `GetStorageInput`. - MissingPasscode, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingUser => write!(f, "`user` was not provided but it is required when building `GetStorageInput`"), - ConstraintViolation::MissingPasscode => write!(f, "`passcode` was not provided but it is required when building `GetStorageInput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ConstraintViolation { - pub(crate) fn as_validation_exception_field( - self, - path: ::std::string::String, - ) -> crate::model::ValidationExceptionField { - match self { - ConstraintViolation::MissingUser => crate::model::ValidationExceptionField { - message: format!("Value at '{}/user' failed to satisfy constraint: Member must not be null", path), - path: path + "/user", - }, - ConstraintViolation::MissingPasscode => crate::model::ValidationExceptionField { - message: format!("Value at '{}/passcode' failed to satisfy constraint: Member must not be null", path), - path: path + "/passcode", - }, - } - } - } - impl ::std::convert::From - for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection - { - fn from(constraint_violation: ConstraintViolation) -> Self { - let first_validation_exception_field = - constraint_violation.as_validation_exception_field("".to_owned()); - let validation_exception = crate::error::ValidationException { - message: format!( - "1 validation error detected. {}", - &first_validation_exception_field.message - ), - field_list: Some(vec![first_validation_exception_field]), - }; - Self::ConstraintViolation( - crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) - .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") - ) - } - } - impl ::std::convert::From - for crate::constrained::MaybeConstrained - { - fn from(builder: Builder) -> Self { - Self::Unconstrained(builder) - } - } - impl ::std::convert::TryFrom for crate::input::GetStorageInput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`GetStorageInput`](crate::input::GetStorageInput). - #[derive(::std::clone::Clone, ::std::default::Default)] - pub struct Builder { - pub(crate) user: ::std::option::Option<::std::string::String>, - pub(crate) passcode: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn user(mut self, input: ::std::string::String) -> Self { - self.user = Some(input); - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_user( - mut self, - input: impl ::std::convert::Into<::std::string::String>, - ) -> Self { - self.user = Some(input.into()); - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn passcode(mut self, input: ::std::string::String) -> Self { - self.passcode = Some(input); - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_passcode( - mut self, - input: impl ::std::convert::Into<::std::string::String>, - ) -> Self { - self.passcode = Some(input.into()); - self - } - /// Consumes the builder and constructs a [`GetStorageInput`](crate::input::GetStorageInput). - /// - /// The builder fails to construct a [`GetStorageInput`](crate::input::GetStorageInput) if a [`ConstraintViolation`] occurs. - /// - /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::input::GetStorageInput { - user: self.user.ok_or(ConstraintViolation::MissingUser)?, - passcode: self.passcode.ok_or(ConstraintViolation::MissingPasscode)?, - }) - } - } - impl ::std::fmt::Debug for Builder { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - let mut formatter = f.debug_struct("Builder"); - formatter.field("user", &self.user); - formatter.field("passcode", &self.passcode); - formatter.finish() - } - } -} -/// See [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). -pub mod get_pokemon_species_input { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `name` was not provided but it is required when building `GetPokemonSpeciesInput`. - MissingName, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingName => write!(f, "`name` was not provided but it is required when building `GetPokemonSpeciesInput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ConstraintViolation { - pub(crate) fn as_validation_exception_field( - self, - path: ::std::string::String, - ) -> crate::model::ValidationExceptionField { - match self { - ConstraintViolation::MissingName => crate::model::ValidationExceptionField { - message: format!( - "Value at '{}/name' failed to satisfy constraint: Member must not be null", - path - ), - path: path + "/name", - }, - } - } - } - impl ::std::convert::From - for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection - { - fn from(constraint_violation: ConstraintViolation) -> Self { - let first_validation_exception_field = - constraint_violation.as_validation_exception_field("".to_owned()); - let validation_exception = crate::error::ValidationException { - message: format!( - "1 validation error detected. {}", - &first_validation_exception_field.message - ), - field_list: Some(vec![first_validation_exception_field]), - }; - Self::ConstraintViolation( - crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) - .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") - ) - } - } - impl ::std::convert::From - for crate::constrained::MaybeConstrained - { - fn from(builder: Builder) -> Self { - Self::Unconstrained(builder) - } - } - impl ::std::convert::TryFrom for crate::input::GetPokemonSpeciesInput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) name: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn name(mut self, input: ::std::string::String) -> Self { - self.name = Some(input); - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_name( - mut self, - input: impl ::std::convert::Into<::std::string::String>, - ) -> Self { - self.name = Some(input.into()); - self - } - /// Consumes the builder and constructs a [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput). - /// - /// The builder fails to construct a [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::input::GetPokemonSpeciesInput { - name: self.name.ok_or(ConstraintViolation::MissingName)?, - }) - } - } -} -/// See [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). -pub mod stream_pokemon_radio_input { - - impl ::std::convert::From for crate::input::StreamPokemonRadioInput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput). - pub fn build(self) -> crate::input::StreamPokemonRadioInput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::input::StreamPokemonRadioInput { - crate::input::StreamPokemonRadioInput {} - } - } -} -/// See [`CheckHealthInput`](crate::input::CheckHealthInput). -pub mod check_health_input { - - impl ::std::convert::From for crate::input::CheckHealthInput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`CheckHealthInput`](crate::input::CheckHealthInput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`CheckHealthInput`](crate::input::CheckHealthInput). - pub fn build(self) -> crate::input::CheckHealthInput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::input::CheckHealthInput { - crate::input::CheckHealthInput {} - } - } -} -/// See [`CapturePokemonInput`](crate::input::CapturePokemonInput). -pub mod capture_pokemon_input { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `events` was not provided but it is required when building `CapturePokemonInput`. - MissingEvents, - /// `region` was not provided but it is required when building `CapturePokemonInput`. - MissingRegion, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingEvents => write!(f, "`events` was not provided but it is required when building `CapturePokemonInput`"), - ConstraintViolation::MissingRegion => write!(f, "`region` was not provided but it is required when building `CapturePokemonInput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ConstraintViolation { - pub(crate) fn as_validation_exception_field( - self, - path: ::std::string::String, - ) -> crate::model::ValidationExceptionField { - match self { - ConstraintViolation::MissingEvents => crate::model::ValidationExceptionField { - message: format!("Value at '{}/events' failed to satisfy constraint: Member must not be null", path), - path: path + "/events", - }, - ConstraintViolation::MissingRegion => crate::model::ValidationExceptionField { - message: format!("Value at '{}/region' failed to satisfy constraint: Member must not be null", path), - path: path + "/region", - }, - } - } - } - impl ::std::convert::From - for ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection - { - fn from(constraint_violation: ConstraintViolation) -> Self { - let first_validation_exception_field = - constraint_violation.as_validation_exception_field("".to_owned()); - let validation_exception = crate::error::ValidationException { - message: format!( - "1 validation error detected. {}", - &first_validation_exception_field.message - ), - field_list: Some(vec![first_validation_exception_field]), - }; - Self::ConstraintViolation( - crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(&validation_exception) - .expect("validation exceptions should never fail to serialize; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues") - ) - } - } - impl ::std::convert::From - for crate::constrained::MaybeConstrained - { - fn from(builder: Builder) -> Self { - Self::Unconstrained(builder) - } - } - impl ::std::convert::TryFrom for crate::input::CapturePokemonInput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`CapturePokemonInput`](crate::input::CapturePokemonInput). - #[derive(::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) events: ::std::option::Option< - ::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - >, - >, - pub(crate) region: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn events( - mut self, - input: ::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - >, - ) -> Self { - self.events = Some(input); - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_events( - mut self, - input: impl ::std::convert::Into< - ::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - >, - >, - ) -> Self { - self.events = Some(input.into()); - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn region(mut self, input: ::std::string::String) -> Self { - self.region = Some(input); - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_region( - mut self, - input: impl ::std::convert::Into<::std::string::String>, - ) -> Self { - self.region = Some(input.into()); - self - } - /// Consumes the builder and constructs a [`CapturePokemonInput`](crate::input::CapturePokemonInput). - /// - /// The builder fails to construct a [`CapturePokemonInput`](crate::input::CapturePokemonInput) if a [`ConstraintViolation`] occurs. - /// - /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::input::CapturePokemonInput { - events: self.events.ok_or(ConstraintViolation::MissingEvents)?, - region: self.region.ok_or(ConstraintViolation::MissingRegion)?, - }) - } - } -} -/// See [`DoNothingInput`](crate::input::DoNothingInput). -pub mod do_nothing_input { - - impl ::std::convert::From for crate::input::DoNothingInput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`DoNothingInput`](crate::input::DoNothingInput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`DoNothingInput`](crate::input::DoNothingInput). - pub fn build(self) -> crate::input::DoNothingInput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::input::DoNothingInput { - crate::input::DoNothingInput {} - } - } -} -/// See [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). -pub mod get_server_statistics_input { - - impl ::std::convert::From for crate::input::GetServerStatisticsInput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput). - pub fn build(self) -> crate::input::GetServerStatisticsInput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::input::GetServerStatisticsInput { - crate::input::GetServerStatisticsInput {} - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/lib.rs b/examples/pokemon-service-server-skd-patch/src/lib.rs deleted file mode 100644 index f3899ee3083..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/lib.rs +++ /dev/null @@ -1,317 +0,0 @@ -#![allow(deprecated)] -#![allow(unknown_lints)] -#![allow(clippy::module_inception)] -#![allow(clippy::upper_case_acronyms)] -#![allow(clippy::large_enum_variant)] -#![allow(clippy::wrong_self_convention)] -#![allow(clippy::should_implement_trait)] -#![allow(clippy::disallowed_names)] -#![allow(clippy::vec_init_then_push)] -#![allow(clippy::type_complexity)] -#![allow(clippy::needless_return)] -#![allow(clippy::derive_partial_eq_without_eq)] -#![allow(clippy::result_large_err)] -#![allow(clippy::unnecessary_map_on_constructor)] -#![allow(clippy::deprecated_semver)] -#![allow(rustdoc::bare_urls)] -#![allow(rustdoc::redundant_explicit_links)] -#![allow(rustdoc::invalid_html_tags)] -#![forbid(unsafe_code)] -#![cfg_attr(docsrs, feature(doc_cfg))] -//! The Pokémon Service allows you to retrieve information about Pokémon species. - -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -//! A fast and customizable Rust implementation of the PokemonService Smithy service. -//! -//! # Using PokemonService -//! -//! The primary entrypoint is [`PokemonService`]: it satisfies the [`Service`](::tower::Service) -//! trait and therefore can be handed to a [`hyper` server](https://github.com/hyperium/hyper) via [`PokemonService::into_make_service`] -//! or used in AWS Lambda -#![cfg_attr( - feature = "aws-lambda", - doc = " via [`LambdaHandler`](crate::server::routing::LambdaHandler)." -)] -#![cfg_attr( - not(feature = "aws-lambda"), - doc = " by enabling the `aws-lambda` feature flag and utilizing the `LambdaHandler`." -)] -//! The [`crate::input`], [`crate::output`], and [`crate::error`] -//! modules provide the types used in each operation. -//! -//! ### Running on Hyper -//! -//! ```rust,no_run -//! # use std::net::SocketAddr; -//! # async fn dummy() { -//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; -//! -//! # let app = PokemonService::builder( -//! # PokemonServiceConfig::builder() -//! # .build() -//! # ).build_unchecked(); -//! use hyper_util::rt::TokioIo; -//! use hyper_util::service::TowerToHyperService; -//! use ::tokio::net::TcpListener; -//! use ::tower::Service; -//! -//! let app = app.into_make_service(); -//! let bind: SocketAddr = "127.0.0.1:6969".parse() -//! .expect("unable to parse the server bind address and port"); -//! let listener = TcpListener::bind(bind).await.expect("failed to bind"); -//! -//! loop { -//! let (stream, remote_addr) = listener.accept().await.expect("failed to accept connection"); -//! let io = TokioIo::new(stream); -//! let mut app = app.clone(); -//! -//! ::tokio::task::spawn(async move { -//! let service = app.call(remote_addr).await.expect("failed to create service"); -//! let hyper_service = TowerToHyperService::new(service); -//! -//! if let Err(err) = ::hyper::server::conn::http1::Builder::new() -//! .serve_connection(io, hyper_service) -//! .await -//! { -//! eprintln!("Error serving connection: {:?}", err); -//! } -//! }); -//! } -//! # } -//! ``` -//! -//! ### Running on Lambda -//! -//! ```rust,ignore -//! use pokemon_service_server_sdk::server::routing::LambdaHandler; -//! use pokemon_service_server_sdk::PokemonService; -//! -//! # async fn dummy() { -//! # let app = PokemonService::builder( -//! # PokemonServiceConfig::builder() -//! # .build() -//! # ).build_unchecked(); -//! let handler = LambdaHandler::new(app); -//! lambda_http::run(handler).await.unwrap(); -//! # } -//! ``` -//! -//! # Building the PokemonService -//! -//! To construct [`PokemonService`] we use [`PokemonServiceBuilder`] returned by [`PokemonService::builder`]. -//! -//! ## Plugins -//! -//! The [`PokemonService::builder`] method, returning [`PokemonServiceBuilder`], -//! accepts a config object on which plugins can be registered. -//! Plugins allow you to build middleware which is aware of the operation it is being applied to. -//! -//! ```rust,no_run -//! # use pokemon_service_server_sdk::server::plugin::IdentityPlugin as LoggingPlugin; -//! # use pokemon_service_server_sdk::server::plugin::IdentityPlugin as MetricsPlugin; -//! use pokemon_service_server_sdk::server::body::BoxBody; -//! use pokemon_service_server_sdk::server::plugin::HttpPlugins; -//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; -//! -//! let http_plugins = HttpPlugins::new() -//! .push(LoggingPlugin) -//! .push(MetricsPlugin); -//! let config = PokemonServiceConfig::builder().http_plugin(http_plugins).build(); -//! let _app = PokemonService::builder::(config).build_unchecked(); -//! ``` -//! -//! Check out [`crate::server::plugin`] to learn more about plugins. -//! -//! ## Handlers -//! -//! [`PokemonServiceBuilder`] provides a setter method for each operation in your Smithy model. The setter methods expect an async function as input, matching the signature for the corresponding operation in your Smithy model. -//! We call these async functions **handlers**. This is where your application business logic lives. -//! -//! Every handler must take an `Input`, and optional [`extractor arguments`](crate::server::request), while returning: -//! -//! * A `Result` if your operation has modeled errors, or -//! * An `Output` otherwise. -//! -//! ```rust,no_run -//! # struct Input; -//! # struct Output; -//! # struct Error; -//! async fn infallible_handler(input: Input) -> Output { todo!() } -//! -//! async fn fallible_handler(input: Input) -> Result { todo!() } -//! ``` -//! -//! Handlers can accept up to 8 extractors: -//! -//! ```rust,no_run -//! # struct Input; -//! # struct Output; -//! # struct Error; -//! # struct State; -//! # use std::net::SocketAddr; -//! use pokemon_service_server_sdk::server::request::{extension::Extension, connect_info::ConnectInfo}; -//! -//! async fn handler_with_no_extensions(input: Input) -> Output { -//! todo!() -//! } -//! -//! async fn handler_with_one_extractor(input: Input, ext: Extension) -> Output { -//! todo!() -//! } -//! -//! async fn handler_with_two_extractors( -//! input: Input, -//! ext0: Extension, -//! ext1: ConnectInfo, -//! ) -> Output { -//! todo!() -//! } -//! ``` -//! -//! See the [`operation module`](crate::operation) for information on precisely what constitutes a handler. -//! -//! ## Build -//! -//! You can convert [`PokemonServiceBuilder`] into [`PokemonService`] using either [`PokemonServiceBuilder::build`] or [`PokemonServiceBuilder::build_unchecked`]. -//! -//! [`PokemonServiceBuilder::build`] requires you to provide a handler for every single operation in your Smithy model. It will return an error if that is not the case. -//! -//! [`PokemonServiceBuilder::build_unchecked`], instead, does not require exhaustiveness. The server will automatically return 500 Internal Server Error to all requests for operations that do not have a registered handler. -//! [`PokemonServiceBuilder::build_unchecked`] is particularly useful if you are deploying your Smithy service as a collection of Lambda functions, where each Lambda is only responsible for a subset of the operations in the Smithy service (or even a single one!). -//! -//! # Example -//! -//! ```rust,no_run -//! # use std::net::SocketAddr; -//! use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; -//! -//! #[::tokio::main] -//! pub async fn main() { -//! let config = PokemonServiceConfig::builder().build(); -//! let app = PokemonService::builder(config) -//! .capture_pokemon(capture_pokemon) -//! .check_health(check_health) -//! .do_nothing(do_nothing) -//! .get_pokemon_species(get_pokemon_species) -//! .get_server_statistics(get_server_statistics) -//! .get_storage(get_storage) -//! .stream_pokemon_radio(stream_pokemon_radio) -//! .build() -//! .expect("failed to build an instance of PokemonService"); -//! -//! use hyper_util::rt::TokioIo; -//! use hyper_util::service::TowerToHyperService; -//! use ::tokio::net::TcpListener; -//! use ::tower::Service; -//! -//! let app = app.into_make_service(); -//! let bind: SocketAddr = "127.0.0.1:6969".parse() -//! .expect("unable to parse the server bind address and port"); -//! let listener = TcpListener::bind(bind).await.expect("failed to bind"); -//! -//! loop { -//! let (stream, remote_addr) = listener.accept().await.expect("failed to accept connection"); -//! let io = TokioIo::new(stream); -//! let mut app = app.clone(); -//! -//! ::tokio::task::spawn(async move { -//! let service = app.call(remote_addr).await.expect("failed to create service"); -//! let hyper_service = TowerToHyperService::new(service); -//! -//! if let Err(err) = ::hyper::server::conn::http1::Builder::new() -//! .serve_connection(io, hyper_service) -//! .await -//! { -//! eprintln!("Error serving connection: {:?}", err); -//! } -//! }); -//! } -//! } -//! -//! use pokemon_service_server_sdk::{input, output, error}; -//! -//! async fn capture_pokemon(input: input::CapturePokemonInput) -> Result { -//! todo!() -//! } -//! -//! async fn check_health(input: input::CheckHealthInput) -> output::CheckHealthOutput { -//! todo!() -//! } -//! -//! async fn do_nothing(input: input::DoNothingInput) -> output::DoNothingOutput { -//! todo!() -//! } -//! -//! async fn get_pokemon_species(input: input::GetPokemonSpeciesInput) -> Result { -//! todo!() -//! } -//! -//! async fn get_server_statistics(input: input::GetServerStatisticsInput) -> output::GetServerStatisticsOutput { -//! todo!() -//! } -//! -//! async fn get_storage(input: input::GetStorageInput) -> Result { -//! todo!() -//! } -//! -//! async fn stream_pokemon_radio(input: input::StreamPokemonRadioInput) -> output::StreamPokemonRadioOutput { -//! todo!() -//! } -//! -//! ``` -//! -//! [`serve`]: https://docs.rs/hyper/0.14.16/hyper/server/struct.Builder.html#method.serve -//! [`tower::make::MakeService`]: https://docs.rs/tower/latest/tower/make/trait.MakeService.html -//! [HTTP binding traits]: https://smithy.io/2.0/spec/http-bindings.html -//! [operations]: https://smithy.io/2.0/spec/service-types.html#operation -//! [hyper server]: https://docs.rs/hyper/latest/hyper/server/index.html -//! [Service]: https://docs.rs/tower-service/latest/tower_service/trait.Service.html -pub use crate::service::{ - MissingOperationsError, PokemonService, PokemonServiceBuilder, PokemonServiceConfig, - PokemonServiceConfigBuilder, -}; - -/// Contains the types that are re-exported from the `aws-smithy-http-server` crate. -pub mod server { - // Re-export all types from the `aws-smithy-http-server` crate. - pub use ::aws_smithy_http_server::*; -} - -/// Crate version number. -pub static PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); - -/// All error types that operations can return. Documentation on these types is copied from the model. -pub mod error; - -/// Input structures for operations. Documentation on these types is copied from the model. -pub mod input; - -/// Data structures used by operation inputs/outputs. Documentation on these types is copied from the model. -pub mod model; - -/// All operations that this crate can perform. -pub mod operation; - -/// A collection of types representing each operation defined in the service closure. -/// -/// The [plugin system](::aws_smithy_http_server::plugin) makes use of these -/// [zero-sized types](https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts) (ZSTs) to -/// parameterize [`Plugin`](::aws_smithy_http_server::plugin::Plugin) implementations. Their traits, such as -/// [`OperationShape`](::aws_smithy_http_server::operation::OperationShape), can be used to provide -/// operation specific information to the [`Layer`](::tower::Layer) being applied. -pub mod operation_shape; - -/// Output structures for operations. Documentation on these types is copied from the model. -pub mod output; - -mod service; - -/// Data primitives referenced by other data types. -pub mod types; - -/// Constrained types for constrained shapes. -mod constrained; - -mod event_stream_serde; - -pub(crate) mod protocol_serde; diff --git a/examples/pokemon-service-server-skd-patch/src/model.rs b/examples/pokemon-service-server-skd-patch/src/model.rs deleted file mode 100644 index 3a3ae63e89b..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/model.rs +++ /dev/null @@ -1,578 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. - -/// Describes one specific validation failure for an input member. -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct ValidationExceptionField { - /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. - pub path: ::std::string::String, - /// A detailed description of the validation failure. - pub message: ::std::string::String, -} -impl ValidationExceptionField { - /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. - pub fn path(&self) -> &str { - use std::ops::Deref; - self.path.deref() - } - /// A detailed description of the validation failure. - pub fn message(&self) -> &str { - use std::ops::Deref; - self.message.deref() - } -} -impl ValidationExceptionField { - /// Creates a new builder-style object to manufacture [`ValidationExceptionField`](crate::model::ValidationExceptionField). - pub fn builder() -> crate::model::validation_exception_field::Builder { - crate::model::validation_exception_field::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct FlavorText { - /// The localized flavor text for an API resource in a specific language. - pub flavor_text: ::std::string::String, - /// The language this name is in. - pub language: crate::model::Language, -} -impl FlavorText { - /// The localized flavor text for an API resource in a specific language. - pub fn flavor_text(&self) -> &str { - use std::ops::Deref; - self.flavor_text.deref() - } - /// The language this name is in. - pub fn language(&self) -> &crate::model::Language { - &self.language - } -} -impl FlavorText { - /// Creates a new builder-style object to manufacture [`FlavorText`](crate::model::FlavorText). - pub fn builder() -> crate::model::flavor_text::Builder { - crate::model::flavor_text::Builder::default() - } -} - -/// Supported languages for FlavorText entries. -#[derive( - ::std::clone::Clone, - ::std::cmp::Eq, - ::std::cmp::Ord, - ::std::cmp::PartialEq, - ::std::cmp::PartialOrd, - ::std::fmt::Debug, - ::std::hash::Hash, -)] -pub enum Language { - /// American English. - English, - /// Español. - Spanish, - /// Italiano. - Italian, - /// 日本語。 - Japanese, -} -/// See [`Language`](crate::model::Language). -pub mod language { - #[derive(Debug, PartialEq)] - pub struct ConstraintViolation(pub(crate) ::std::string::String); - - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - r#"Value provided for 'com.aws.example#Language' failed to satisfy constraint: Member must satisfy enum value set: [en, es, it, jp]"# - ) - } - } - - impl ::std::error::Error for ConstraintViolation {} -} -impl ::std::convert::TryFrom<&str> for Language { - type Error = crate::model::language::ConstraintViolation; - fn try_from( - s: &str, - ) -> ::std::result::Result>::Error> { - match s { - "en" => Ok(Language::English), - "es" => Ok(Language::Spanish), - "it" => Ok(Language::Italian), - "jp" => Ok(Language::Japanese), - _ => Err(crate::model::language::ConstraintViolation(s.to_owned())), - } - } -} -impl ::std::convert::TryFrom<::std::string::String> for Language { - type Error = crate::model::language::ConstraintViolation; - fn try_from( - s: ::std::string::String, - ) -> ::std::result::Result>::Error> - { - s.as_str().try_into() - } -} -impl std::str::FromStr for Language { - type Err = crate::model::language::ConstraintViolation; - fn from_str(s: &str) -> std::result::Result::Err> { - Self::try_from(s) - } -} -impl Language { - /// Returns the `&str` value of the enum member. - pub fn as_str(&self) -> &str { - match self { - Language::English => "en", - Language::Spanish => "es", - Language::Italian => "it", - Language::Japanese => "jp", - } - } - /// Returns all the `&str` representations of the enum members. - pub const fn values() -> &'static [&'static str] { - &["en", "es", "it", "jp"] - } -} -impl ::std::convert::AsRef for Language { - fn as_ref(&self) -> &str { - self.as_str() - } -} -impl crate::constrained::Constrained for Language { - type Unconstrained = ::std::string::String; -} - -impl ::std::convert::From<::std::string::String> - for crate::constrained::MaybeConstrained -{ - fn from(value: ::std::string::String) -> Self { - Self::Unconstrained(value) - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)] -pub enum CapturePokemonEvents { - #[allow(missing_docs)] // documentation missing in model - Event(crate::model::CaptureEvent), -} -impl CapturePokemonEvents { - #[allow(irrefutable_let_patterns)] - /// Tries to convert the enum instance into [`Event`](crate::model::CapturePokemonEvents::Event), extracting the inner [`CaptureEvent`](crate::model::CaptureEvent). - /// Returns `Err(&Self)` if it can't be converted. - pub fn as_event(&self) -> ::std::result::Result<&crate::model::CaptureEvent, &Self> { - if let CapturePokemonEvents::Event(val) = &self { - ::std::result::Result::Ok(val) - } else { - ::std::result::Result::Err(self) - } - } - /// Returns true if this is a [`Event`](crate::model::CapturePokemonEvents::Event). - pub fn is_event(&self) -> bool { - self.as_event().is_ok() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct CaptureEvent { - #[allow(missing_docs)] // documentation missing in model - pub name: ::std::option::Option<::std::string::String>, - #[allow(missing_docs)] // documentation missing in model - pub captured: ::std::option::Option, - #[allow(missing_docs)] // documentation missing in model - pub shiny: ::std::option::Option, - #[allow(missing_docs)] // documentation missing in model - pub pokedex_update: ::std::option::Option<::aws_smithy_types::Blob>, -} -impl CaptureEvent { - #[allow(missing_docs)] // documentation missing in model - pub fn name(&self) -> ::std::option::Option<&str> { - self.name.as_deref() - } - #[allow(missing_docs)] // documentation missing in model - pub fn captured(&self) -> ::std::option::Option { - self.captured - } - #[allow(missing_docs)] // documentation missing in model - pub fn shiny(&self) -> ::std::option::Option { - self.shiny - } - #[allow(missing_docs)] // documentation missing in model - pub fn pokedex_update(&self) -> ::std::option::Option<&::aws_smithy_types::Blob> { - self.pokedex_update.as_ref() - } -} -impl CaptureEvent { - /// Creates a new builder-style object to manufacture [`CaptureEvent`](crate::model::CaptureEvent). - pub fn builder() -> crate::model::capture_event::Builder { - crate::model::capture_event::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)] -pub enum AttemptCapturingPokemonEvent { - #[allow(missing_docs)] // documentation missing in model - Event(crate::model::CapturingEvent), -} -impl AttemptCapturingPokemonEvent { - #[allow(irrefutable_let_patterns)] - /// Tries to convert the enum instance into [`Event`](crate::model::AttemptCapturingPokemonEvent::Event), extracting the inner [`CapturingEvent`](crate::model::CapturingEvent). - /// Returns `Err(&Self)` if it can't be converted. - pub fn as_event(&self) -> ::std::result::Result<&crate::model::CapturingEvent, &Self> { - if let AttemptCapturingPokemonEvent::Event(val) = &self { - ::std::result::Result::Ok(val) - } else { - ::std::result::Result::Err(self) - } - } - /// Returns true if this is a [`Event`](crate::model::AttemptCapturingPokemonEvent::Event). - pub fn is_event(&self) -> bool { - self.as_event().is_ok() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct CapturingEvent { - #[allow(missing_docs)] // documentation missing in model - pub payload: ::std::option::Option, -} -impl CapturingEvent { - #[allow(missing_docs)] // documentation missing in model - pub fn payload(&self) -> ::std::option::Option<&crate::model::CapturingPayload> { - self.payload.as_ref() - } -} -impl CapturingEvent { - /// Creates a new builder-style object to manufacture [`CapturingEvent`](crate::model::CapturingEvent). - pub fn builder() -> crate::model::capturing_event::Builder { - crate::model::capturing_event::Builder::default() - } -} -impl crate::constrained::Constrained for crate::model::CapturingEvent { - type Unconstrained = crate::model::capturing_event::Builder; -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct CapturingPayload { - #[allow(missing_docs)] // documentation missing in model - pub name: ::std::option::Option<::std::string::String>, - #[allow(missing_docs)] // documentation missing in model - pub pokeball: ::std::option::Option<::std::string::String>, -} -impl CapturingPayload { - #[allow(missing_docs)] // documentation missing in model - pub fn name(&self) -> ::std::option::Option<&str> { - self.name.as_deref() - } - #[allow(missing_docs)] // documentation missing in model - pub fn pokeball(&self) -> ::std::option::Option<&str> { - self.pokeball.as_deref() - } -} -impl CapturingPayload { - /// Creates a new builder-style object to manufacture [`CapturingPayload`](crate::model::CapturingPayload). - pub fn builder() -> crate::model::capturing_payload::Builder { - crate::model::capturing_payload::Builder::default() - } -} -impl crate::constrained::Constrained for crate::model::CapturingPayload { - type Unconstrained = crate::model::capturing_payload::Builder; -} -/// See [`ValidationExceptionField`](crate::model::ValidationExceptionField). -pub mod validation_exception_field { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `path` was not provided but it is required when building `ValidationExceptionField`. - MissingPath, - /// `message` was not provided but it is required when building `ValidationExceptionField`. - MissingMessage, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingPath => write!(f, "`path` was not provided but it is required when building `ValidationExceptionField`"), - ConstraintViolation::MissingMessage => write!(f, "`message` was not provided but it is required when building `ValidationExceptionField`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::model::ValidationExceptionField { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`ValidationExceptionField`](crate::model::ValidationExceptionField). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) path: ::std::option::Option<::std::string::String>, - pub(crate) message: ::std::option::Option<::std::string::String>, - } - impl Builder { - /// A JSONPointer expression to the structure member whose value failed to satisfy the modeled constraints. - pub fn path(mut self, input: ::std::string::String) -> Self { - self.path = Some(input); - self - } - /// A detailed description of the validation failure. - pub fn message(mut self, input: ::std::string::String) -> Self { - self.message = Some(input); - self - } - /// Consumes the builder and constructs a [`ValidationExceptionField`](crate::model::ValidationExceptionField). - /// - /// The builder fails to construct a [`ValidationExceptionField`](crate::model::ValidationExceptionField) if a [`ConstraintViolation`] occurs. - /// - /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::model::ValidationExceptionField { - path: self.path.ok_or(ConstraintViolation::MissingPath)?, - message: self.message.ok_or(ConstraintViolation::MissingMessage)?, - }) - } - } -} -/// See [`FlavorText`](crate::model::FlavorText). -pub mod flavor_text { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `flavor_text` was not provided but it is required when building `FlavorText`. - MissingFlavorText, - /// `language` was not provided but it is required when building `FlavorText`. - MissingLanguage, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingFlavorText => write!( - f, - "`flavor_text` was not provided but it is required when building `FlavorText`" - ), - ConstraintViolation::MissingLanguage => write!( - f, - "`language` was not provided but it is required when building `FlavorText`" - ), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::model::FlavorText { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`FlavorText`](crate::model::FlavorText). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) flavor_text: ::std::option::Option<::std::string::String>, - pub(crate) language: ::std::option::Option, - } - impl Builder { - /// The localized flavor text for an API resource in a specific language. - pub fn flavor_text(mut self, input: ::std::string::String) -> Self { - self.flavor_text = Some(input); - self - } - /// The language this name is in. - pub fn language(mut self, input: crate::model::Language) -> Self { - self.language = Some(input); - self - } - /// Consumes the builder and constructs a [`FlavorText`](crate::model::FlavorText). - /// - /// The builder fails to construct a [`FlavorText`](crate::model::FlavorText) if a [`ConstraintViolation`] occurs. - /// - /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::model::FlavorText { - flavor_text: self - .flavor_text - .ok_or(ConstraintViolation::MissingFlavorText)?, - language: self.language.ok_or(ConstraintViolation::MissingLanguage)?, - }) - } - } -} -/// See [`CaptureEvent`](crate::model::CaptureEvent). -pub mod capture_event { - - impl ::std::convert::From for crate::model::CaptureEvent { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`CaptureEvent`](crate::model::CaptureEvent). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) name: ::std::option::Option<::std::string::String>, - pub(crate) captured: ::std::option::Option, - pub(crate) shiny: ::std::option::Option, - pub(crate) pokedex_update: ::std::option::Option<::aws_smithy_types::Blob>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn name(mut self, input: ::std::option::Option<::std::string::String>) -> Self { - self.name = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn captured(mut self, input: ::std::option::Option) -> Self { - self.captured = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn shiny(mut self, input: ::std::option::Option) -> Self { - self.shiny = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn pokedex_update( - mut self, - input: ::std::option::Option<::aws_smithy_types::Blob>, - ) -> Self { - self.pokedex_update = input; - self - } - /// Consumes the builder and constructs a [`CaptureEvent`](crate::model::CaptureEvent). - pub fn build(self) -> crate::model::CaptureEvent { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::model::CaptureEvent { - crate::model::CaptureEvent { - name: self.name, - captured: self.captured, - shiny: self.shiny, - pokedex_update: self.pokedex_update, - } - } - } -} -/// See [`CapturingEvent`](crate::model::CapturingEvent). -pub mod capturing_event { - - impl ::std::convert::From for crate::model::CapturingEvent { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`CapturingEvent`](crate::model::CapturingEvent). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) payload: ::std::option::Option, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn payload( - mut self, - input: ::std::option::Option, - ) -> Self { - self.payload = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_payload( - mut self, - input: Option>, - ) -> Self { - self.payload = input.map(|v| v.into()); - self - } - /// Consumes the builder and constructs a [`CapturingEvent`](crate::model::CapturingEvent). - pub fn build(self) -> crate::model::CapturingEvent { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::model::CapturingEvent { - crate::model::CapturingEvent { - payload: self.payload, - } - } - } -} -/// See [`CapturingPayload`](crate::model::CapturingPayload). -pub mod capturing_payload { - - impl ::std::convert::From for crate::model::CapturingPayload { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`CapturingPayload`](crate::model::CapturingPayload). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) name: ::std::option::Option<::std::string::String>, - pub(crate) pokeball: ::std::option::Option<::std::string::String>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn name(mut self, input: ::std::option::Option<::std::string::String>) -> Self { - self.name = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_name( - mut self, - input: Option>, - ) -> Self { - self.name = input.map(|v| v.into()); - self - } - #[allow(missing_docs)] // documentation missing in model - pub fn pokeball(mut self, input: ::std::option::Option<::std::string::String>) -> Self { - self.pokeball = input; - self - } - #[allow(missing_docs)] // documentation missing in model - pub(crate) fn set_pokeball( - mut self, - input: Option>, - ) -> Self { - self.pokeball = input.map(|v| v.into()); - self - } - /// Consumes the builder and constructs a [`CapturingPayload`](crate::model::CapturingPayload). - pub fn build(self) -> crate::model::CapturingPayload { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::model::CapturingPayload { - crate::model::CapturingPayload { - name: self.name, - pokeball: self.pokeball, - } - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/operation.rs b/examples/pokemon-service-server-skd-patch/src/operation.rs deleted file mode 100644 index 5fe1e67bbeb..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/operation.rs +++ /dev/null @@ -1,639 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -const CONTENT_TYPE_GETSTORAGE: ::mime::Mime = ::mime::APPLICATION_JSON; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`GetStorageInput`](crate::input::GetStorageInput) using modelled bindings. - pub struct GetStorageInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for GetStorageInputFuture { - type Output = Result< - crate::input::GetStorageInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::GetStorageInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = GetStorageInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_GETSTORAGE, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_get_storage::de_get_storage_http_request(request).await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - GetStorageInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::GetStorageOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_get_storage::ser_get_storage_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::error::GetStorageError -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_get_storage::ser_get_storage_http_error(&self) { - Ok(mut response) => { - response.extensions_mut().insert( - ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), - ); - response - } - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -const CONTENT_TYPE_GETPOKEMONSPECIES: ::mime::Mime = ::mime::APPLICATION_JSON; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`GetPokemonSpeciesInput`](crate::input::GetPokemonSpeciesInput) using modelled bindings. - pub struct GetPokemonSpeciesInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for GetPokemonSpeciesInputFuture { - type Output = Result< - crate::input::GetPokemonSpeciesInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::GetPokemonSpeciesInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = GetPokemonSpeciesInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_GETPOKEMONSPECIES, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_get_pokemon_species::de_get_pokemon_species_http_request( - request, - ) - .await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - GetPokemonSpeciesInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::GetPokemonSpeciesOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_get_pokemon_species::ser_get_pokemon_species_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::error::GetPokemonSpeciesError -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_get_pokemon_species::ser_get_pokemon_species_http_error( - &self, - ) { - Ok(mut response) => { - response.extensions_mut().insert( - ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), - ); - response - } - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -const CONTENT_TYPE_STREAMPOKEMONRADIO: ::mime::Mime = ::mime::APPLICATION_OCTET_STREAM; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`StreamPokemonRadioInput`](crate::input::StreamPokemonRadioInput) using modelled bindings. - pub struct StreamPokemonRadioInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for StreamPokemonRadioInputFuture { - type Output = Result< - crate::input::StreamPokemonRadioInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::StreamPokemonRadioInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = StreamPokemonRadioInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_STREAMPOKEMONRADIO, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_stream_pokemon_radio::de_stream_pokemon_radio_http_request( - request, - ) - .await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - StreamPokemonRadioInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::StreamPokemonRadioOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_stream_pokemon_radio::ser_stream_pokemon_radio_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -const CONTENT_TYPE_CHECKHEALTH: ::mime::Mime = ::mime::APPLICATION_JSON; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`CheckHealthInput`](crate::input::CheckHealthInput) using modelled bindings. - pub struct CheckHealthInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for CheckHealthInputFuture { - type Output = Result< - crate::input::CheckHealthInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::CheckHealthInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = CheckHealthInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_CHECKHEALTH, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_check_health::de_check_health_http_request(request).await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - CheckHealthInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::CheckHealthOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_check_health::ser_check_health_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -static CONTENT_TYPE_CAPTUREPOKEMON: std::sync::LazyLock<::mime::Mime> = - std::sync::LazyLock::new(|| { - "application/vnd.amazon.eventstream" - .parse::<::mime::Mime>() - .expect("BUG: MIME parsing failed, content_type is not valid") - }); -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`CapturePokemonInput`](crate::input::CapturePokemonInput) using modelled bindings. - pub struct CapturePokemonInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for CapturePokemonInputFuture { - type Output = Result< - crate::input::CapturePokemonInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::CapturePokemonInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - // TODO: PATCH - Changed from Into to http-body 1.x constraint for hyper 1.x compatibility - // This supports any body type that implements http-body 1.x (including custom body types) - B: http_body_1_0::Body + Send + Sync + 'static, - B::Error: Into<::aws_smithy_types::body::Error> + 'static, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = CapturePokemonInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_CAPTUREPOKEMON, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_capture_pokemon::de_capture_pokemon_http_request(request) - .await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - CapturePokemonInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::CapturePokemonOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_capture_pokemon::ser_capture_pokemon_http_response(self) - { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::error::CapturePokemonError -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_capture_pokemon::ser_capture_pokemon_http_error(&self) { - Ok(mut response) => { - response.extensions_mut().insert( - ::aws_smithy_http_server::extension::ModeledErrorExtension::new(self.name()), - ); - response - } - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -const CONTENT_TYPE_DONOTHING: ::mime::Mime = ::mime::APPLICATION_JSON; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`DoNothingInput`](crate::input::DoNothingInput) using modelled bindings. - pub struct DoNothingInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for DoNothingInputFuture { - type Output = Result< - crate::input::DoNothingInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::DoNothingInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = DoNothingInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_DONOTHING, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_do_nothing::de_do_nothing_http_request(request).await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - DoNothingInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::DoNothingOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_do_nothing::ser_do_nothing_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} - -const CONTENT_TYPE_GETSERVERSTATISTICS: ::mime::Mime = ::mime::APPLICATION_JSON; -::pin_project_lite::pin_project! { - /// A [`Future`](std::future::Future) aggregating the body bytes of a [`Request`] and constructing the - /// [`GetServerStatisticsInput`](crate::input::GetServerStatisticsInput) using modelled bindings. - pub struct GetServerStatisticsInputFuture { - inner: std::pin::Pin> + Send>> - } -} - -impl std::future::Future for GetServerStatisticsInputFuture { - type Output = Result< - crate::input::GetServerStatisticsInput, - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError, - >; - - fn poll( - self: std::pin::Pin<&mut Self>, - cx: &mut std::task::Context<'_>, - ) -> std::task::Poll { - let this = self.project(); - this.inner.as_mut().poll(cx) - } -} - -impl - ::aws_smithy_http_server::request::FromRequest< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - B, - > for crate::input::GetServerStatisticsInput -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B: 'static, - - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - type Rejection = ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError; - type Future = GetServerStatisticsInputFuture; - - fn from_request(request: ::http::Request) -> Self::Future { - let fut = async move { - if !::aws_smithy_http_server::protocol::accept_header_classifier( - request.headers(), - &CONTENT_TYPE_GETSERVERSTATISTICS, - ) { - return Err(::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection::NotAcceptable); - } - crate::protocol_serde::shape_get_server_statistics::de_get_server_statistics_http_request(request) - .await - }; - use ::futures_util::future::TryFutureExt; - let fut = fut.map_err( - |e: ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection| { - ::tracing::debug!(error = %e, "failed to deserialize request"); - ::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from( - e, - ) - }, - ); - GetServerStatisticsInputFuture { - inner: Box::pin(fut), - } - } -} -impl - ::aws_smithy_http_server::response::IntoResponse< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - > for crate::output::GetServerStatisticsOutput -{ - fn into_response(self) -> ::aws_smithy_http_server::response::Response { - match crate::protocol_serde::shape_get_server_statistics::ser_get_server_statistics_http_response(self) { - Ok(response) => response, - Err(e) => { - ::tracing::error!(error = %e, "failed to serialize response"); - ::aws_smithy_http_server::response::IntoResponse::<::aws_smithy_http_server::protocol::rest_json_1::RestJson1>::into_response(::aws_smithy_http_server::protocol::rest_json_1::runtime_error::RuntimeError::from(e)) - } - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/operation_shape.rs b/examples/pokemon-service-server-skd-patch/src/operation_shape.rs deleted file mode 100644 index 1f5b0455292..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/operation_shape.rs +++ /dev/null @@ -1,289 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. - -/// Retrieve information about your Pokédex. -pub struct GetStorage; - -impl ::aws_smithy_http_server::operation::OperationShape for GetStorage { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetStorage", - "com.aws.example", - "GetStorage", - ); - - type Input = crate::input::GetStorageInput; - type Output = crate::output::GetStorageOutput; - type Error = crate::error::GetStorageError; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetStorage { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::sensitivity::headers::MakeHeaders< - fn( - &::http::header::HeaderName, - ) - -> ::aws_smithy_http_server::instrumentation::sensitivity::headers::HeaderMarker, - >, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeLabel< - fn(usize) -> bool, - >, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - .header({ - |name: &::http::header::HeaderName| { - let name_match = matches!(name.as_str(), "passcode"); - let key_suffix = None; - let value = name_match; - ::aws_smithy_http_server::instrumentation::sensitivity::headers::HeaderMarker { - key_suffix, - value, - } - } - } as fn(&_) -> _) - .label( - { |index: usize| matches!(index, 1) } as fn(usize) -> bool, - None, - ) - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// Retrieve information about a Pokémon species. -pub struct GetPokemonSpecies; - -impl ::aws_smithy_http_server::operation::OperationShape for GetPokemonSpecies { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetPokemonSpecies", - "com.aws.example", - "GetPokemonSpecies", - ); - - type Input = crate::input::GetPokemonSpeciesInput; - type Output = crate::output::GetPokemonSpeciesOutput; - type Error = crate::error::GetPokemonSpeciesError; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetPokemonSpecies { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// Fetch a radio song from the database and stream it back as a playable audio. -pub struct StreamPokemonRadio; - -impl ::aws_smithy_http_server::operation::OperationShape for StreamPokemonRadio { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#StreamPokemonRadio", - "com.aws.example", - "StreamPokemonRadio", - ); - - type Input = crate::input::StreamPokemonRadioInput; - type Output = crate::output::StreamPokemonRadioOutput; - type Error = std::convert::Infallible; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for StreamPokemonRadio { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// Health check operation, to check the service is up Not yet a deep check -pub struct CheckHealth; - -impl ::aws_smithy_http_server::operation::OperationShape for CheckHealth { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#CheckHealth", - "com.aws.example", - "CheckHealth", - ); - - type Input = crate::input::CheckHealthInput; - type Output = crate::output::CheckHealthOutput; - type Error = std::convert::Infallible; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for CheckHealth { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// Capture Pokémons via event streams. -pub struct CapturePokemon; - -impl ::aws_smithy_http_server::operation::OperationShape for CapturePokemon { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#CapturePokemon", - "com.aws.example", - "CapturePokemon", - ); - - type Input = crate::input::CapturePokemonInput; - type Output = crate::output::CapturePokemonOutput; - type Error = crate::error::CapturePokemonError; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for CapturePokemon { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// DoNothing operation, used to stress test the framework. -pub struct DoNothing; - -impl ::aws_smithy_http_server::operation::OperationShape for DoNothing { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#DoNothing", - "com.aws.example", - "DoNothing", - ); - - type Input = crate::input::DoNothingInput; - type Output = crate::output::DoNothingOutput; - type Error = std::convert::Infallible; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for DoNothing { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} - -/// Retrieve HTTP server statistiscs, such as calls count. -pub struct GetServerStatistics; - -impl ::aws_smithy_http_server::operation::OperationShape for GetServerStatistics { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetServerStatistics", - "com.aws.example", - "GetServerStatistics", - ); - - type Input = crate::input::GetServerStatisticsInput; - type Output = crate::output::GetServerStatisticsOutput; - type Error = std::convert::Infallible; -} - -impl ::aws_smithy_http_server::instrumentation::sensitivity::Sensitivity for GetServerStatistics { - type RequestFmt = ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::sensitivity::uri::MakeUri< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >, - >; - type ResponseFmt = ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt< - ::aws_smithy_http_server::instrumentation::MakeIdentity, - ::aws_smithy_http_server::instrumentation::MakeIdentity, - >; - - fn request_fmt() -> Self::RequestFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::RequestFmt::new() - } - - fn response_fmt() -> Self::ResponseFmt { - ::aws_smithy_http_server::instrumentation::sensitivity::ResponseFmt::new() - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/output.rs b/examples/pokemon-service-server-skd-patch/src/output.rs deleted file mode 100644 index c45ad71a145..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/output.rs +++ /dev/null @@ -1,461 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. - -/// Contents of the Pokémon storage. -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct GetStorageOutput { - /// A list of Pokémon species. - pub collection: ::std::vec::Vec<::std::string::String>, -} -impl GetStorageOutput { - /// A list of Pokémon species. - pub fn collection(&self) -> &[::std::string::String] { - use std::ops::Deref; - self.collection.deref() - } -} -impl GetStorageOutput { - /// Creates a new builder-style object to manufacture [`GetStorageOutput`](crate::output::GetStorageOutput). - pub fn builder() -> crate::output::get_storage_output::Builder { - crate::output::get_storage_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct GetPokemonSpeciesOutput { - /// The name for this resource. - pub name: ::std::string::String, - /// A list of flavor text entries for this Pokémon species. - pub flavor_text_entries: ::std::vec::Vec, -} -impl GetPokemonSpeciesOutput { - /// The name for this resource. - pub fn name(&self) -> &str { - use std::ops::Deref; - self.name.deref() - } - /// A list of flavor text entries for this Pokémon species. - pub fn flavor_text_entries(&self) -> &[crate::model::FlavorText] { - use std::ops::Deref; - self.flavor_text_entries.deref() - } -} -impl GetPokemonSpeciesOutput { - /// Creates a new builder-style object to manufacture [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). - pub fn builder() -> crate::output::get_pokemon_species_output::Builder { - crate::output::get_pokemon_species_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive(::std::fmt::Debug)] -pub struct StreamPokemonRadioOutput { - #[allow(missing_docs)] // documentation missing in model - pub data: ::aws_smithy_types::byte_stream::ByteStream, -} -impl StreamPokemonRadioOutput { - #[allow(missing_docs)] // documentation missing in model - pub fn data(&self) -> &::aws_smithy_types::byte_stream::ByteStream { - &self.data - } -} -impl StreamPokemonRadioOutput { - /// Creates a new builder-style object to manufacture [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). - pub fn builder() -> crate::output::stream_pokemon_radio_output::Builder { - crate::output::stream_pokemon_radio_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct CheckHealthOutput {} -impl CheckHealthOutput { - /// Creates a new builder-style object to manufacture [`CheckHealthOutput`](crate::output::CheckHealthOutput). - pub fn builder() -> crate::output::check_health_output::Builder { - crate::output::check_health_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive(::std::fmt::Debug)] -pub struct CapturePokemonOutput { - #[allow(missing_docs)] // documentation missing in model - pub events: ::aws_smithy_http::event_stream::EventStreamSender< - crate::model::CapturePokemonEvents, - crate::error::CapturePokemonEventsError, - >, -} -impl CapturePokemonOutput { - #[allow(missing_docs)] // documentation missing in model - pub fn events( - &self, - ) -> &::aws_smithy_http::event_stream::EventStreamSender< - crate::model::CapturePokemonEvents, - crate::error::CapturePokemonEventsError, - > { - &self.events - } -} -impl CapturePokemonOutput { - /// Creates a new builder-style object to manufacture [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). - pub fn builder() -> crate::output::capture_pokemon_output::Builder { - crate::output::capture_pokemon_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct DoNothingOutput {} -impl DoNothingOutput { - /// Creates a new builder-style object to manufacture [`DoNothingOutput`](crate::output::DoNothingOutput). - pub fn builder() -> crate::output::do_nothing_output::Builder { - crate::output::do_nothing_output::Builder::default() - } -} - -#[allow(missing_docs)] // documentation missing in model -#[derive( - ::std::clone::Clone, ::std::cmp::Eq, ::std::cmp::PartialEq, ::std::fmt::Debug, ::std::hash::Hash, -)] -pub struct GetServerStatisticsOutput { - /// The number of calls executed by the server. - pub calls_count: i64, -} -impl GetServerStatisticsOutput { - /// The number of calls executed by the server. - pub fn calls_count(&self) -> i64 { - self.calls_count - } -} -impl GetServerStatisticsOutput { - /// Creates a new builder-style object to manufacture [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). - pub fn builder() -> crate::output::get_server_statistics_output::Builder { - crate::output::get_server_statistics_output::Builder::default() - } -} -/// See [`GetStorageOutput`](crate::output::GetStorageOutput). -pub mod get_storage_output { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `collection` was not provided but it is required when building `GetStorageOutput`. - MissingCollection, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingCollection => write!(f, "`collection` was not provided but it is required when building `GetStorageOutput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::output::GetStorageOutput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`GetStorageOutput`](crate::output::GetStorageOutput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) collection: ::std::option::Option<::std::vec::Vec<::std::string::String>>, - } - impl Builder { - /// A list of Pokémon species. - pub fn collection(mut self, input: ::std::vec::Vec<::std::string::String>) -> Self { - self.collection = Some(input); - self - } - /// Consumes the builder and constructs a [`GetStorageOutput`](crate::output::GetStorageOutput). - /// - /// The builder fails to construct a [`GetStorageOutput`](crate::output::GetStorageOutput) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::output::GetStorageOutput { - collection: self - .collection - .ok_or(ConstraintViolation::MissingCollection)?, - }) - } - } -} -/// See [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). -pub mod get_pokemon_species_output { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `name` was not provided but it is required when building `GetPokemonSpeciesOutput`. - MissingName, - /// `flavor_text_entries` was not provided but it is required when building `GetPokemonSpeciesOutput`. - MissingFlavorTextEntries, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingName => write!(f, "`name` was not provided but it is required when building `GetPokemonSpeciesOutput`"), - ConstraintViolation::MissingFlavorTextEntries => write!(f, "`flavor_text_entries` was not provided but it is required when building `GetPokemonSpeciesOutput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::output::GetPokemonSpeciesOutput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) name: ::std::option::Option<::std::string::String>, - pub(crate) flavor_text_entries: - ::std::option::Option<::std::vec::Vec>, - } - impl Builder { - /// The name for this resource. - pub fn name(mut self, input: ::std::string::String) -> Self { - self.name = Some(input); - self - } - /// A list of flavor text entries for this Pokémon species. - pub fn flavor_text_entries( - mut self, - input: ::std::vec::Vec, - ) -> Self { - self.flavor_text_entries = Some(input); - self - } - /// Consumes the builder and constructs a [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput). - /// - /// The builder fails to construct a [`GetPokemonSpeciesOutput`](crate::output::GetPokemonSpeciesOutput) if a [`ConstraintViolation`] occurs. - /// - /// If the builder fails, it will return the _first_ encountered [`ConstraintViolation`]. - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::output::GetPokemonSpeciesOutput { - name: self.name.ok_or(ConstraintViolation::MissingName)?, - flavor_text_entries: self - .flavor_text_entries - .ok_or(ConstraintViolation::MissingFlavorTextEntries)?, - }) - } - } -} -/// See [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). -pub mod stream_pokemon_radio_output { - - impl ::std::convert::From for crate::output::StreamPokemonRadioOutput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). - #[derive(::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) data: ::std::option::Option<::aws_smithy_types::byte_stream::ByteStream>, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn data(mut self, input: ::aws_smithy_types::byte_stream::ByteStream) -> Self { - self.data = Some(input); - self - } - /// Consumes the builder and constructs a [`StreamPokemonRadioOutput`](crate::output::StreamPokemonRadioOutput). - pub fn build(self) -> crate::output::StreamPokemonRadioOutput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::output::StreamPokemonRadioOutput { - crate::output::StreamPokemonRadioOutput { - data: self.data.unwrap_or_default(), - } - } - } -} -/// See [`CheckHealthOutput`](crate::output::CheckHealthOutput). -pub mod check_health_output { - - impl ::std::convert::From for crate::output::CheckHealthOutput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`CheckHealthOutput`](crate::output::CheckHealthOutput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`CheckHealthOutput`](crate::output::CheckHealthOutput). - pub fn build(self) -> crate::output::CheckHealthOutput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::output::CheckHealthOutput { - crate::output::CheckHealthOutput {} - } - } -} -/// See [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). -pub mod capture_pokemon_output { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `events` was not provided but it is required when building `CapturePokemonOutput`. - MissingEvents, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingEvents => write!(f, "`events` was not provided but it is required when building `CapturePokemonOutput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::output::CapturePokemonOutput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). - #[derive(::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) events: ::std::option::Option< - ::aws_smithy_http::event_stream::EventStreamSender< - crate::model::CapturePokemonEvents, - crate::error::CapturePokemonEventsError, - >, - >, - } - impl Builder { - #[allow(missing_docs)] // documentation missing in model - pub fn events( - mut self, - input: ::aws_smithy_http::event_stream::EventStreamSender< - crate::model::CapturePokemonEvents, - crate::error::CapturePokemonEventsError, - >, - ) -> Self { - self.events = Some(input); - self - } - /// Consumes the builder and constructs a [`CapturePokemonOutput`](crate::output::CapturePokemonOutput). - /// - /// The builder fails to construct a [`CapturePokemonOutput`](crate::output::CapturePokemonOutput) if a [`ConstraintViolation`] occurs. - /// - pub fn build(self) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::output::CapturePokemonOutput { - events: self.events.ok_or(ConstraintViolation::MissingEvents)?, - }) - } - } -} -/// See [`DoNothingOutput`](crate::output::DoNothingOutput). -pub mod do_nothing_output { - - impl ::std::convert::From for crate::output::DoNothingOutput { - fn from(builder: Builder) -> Self { - builder.build() - } - } - /// A builder for [`DoNothingOutput`](crate::output::DoNothingOutput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder {} - impl Builder { - /// Consumes the builder and constructs a [`DoNothingOutput`](crate::output::DoNothingOutput). - pub fn build(self) -> crate::output::DoNothingOutput { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints(self) -> crate::output::DoNothingOutput { - crate::output::DoNothingOutput {} - } - } -} -/// See [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). -pub mod get_server_statistics_output { - - #[derive(::std::cmp::PartialEq, ::std::fmt::Debug)] - /// Holds one variant for each of the ways the builder can fail. - #[non_exhaustive] - #[allow(clippy::enum_variant_names)] - pub enum ConstraintViolation { - /// `calls_count` was not provided but it is required when building `GetServerStatisticsOutput`. - MissingCallsCount, - } - impl ::std::fmt::Display for ConstraintViolation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ConstraintViolation::MissingCallsCount => write!(f, "`calls_count` was not provided but it is required when building `GetServerStatisticsOutput`"), - } - } - } - impl ::std::error::Error for ConstraintViolation {} - impl ::std::convert::TryFrom for crate::output::GetServerStatisticsOutput { - type Error = ConstraintViolation; - - fn try_from(builder: Builder) -> ::std::result::Result { - builder.build() - } - } - /// A builder for [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). - #[derive(::std::clone::Clone, ::std::default::Default, ::std::fmt::Debug)] - pub struct Builder { - pub(crate) calls_count: ::std::option::Option, - } - impl Builder { - /// The number of calls executed by the server. - pub fn calls_count(mut self, input: i64) -> Self { - self.calls_count = Some(input); - self - } - /// Consumes the builder and constructs a [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput). - /// - /// The builder fails to construct a [`GetServerStatisticsOutput`](crate::output::GetServerStatisticsOutput) if a [`ConstraintViolation`] occurs. - /// - pub fn build( - self, - ) -> Result { - self.build_enforcing_all_constraints() - } - fn build_enforcing_all_constraints( - self, - ) -> Result { - Ok(crate::output::GetServerStatisticsOutput { - calls_count: self - .calls_count - .ok_or(ConstraintViolation::MissingCallsCount)?, - }) - } - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs deleted file mode 100644 index 7b5ea4e8e63..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub(crate) mod shape_capture_pokemon; - -pub(crate) mod shape_check_health; - -pub(crate) mod shape_do_nothing; - -pub(crate) mod shape_get_pokemon_species; - -pub(crate) mod shape_get_server_statistics; - -pub(crate) mod shape_get_storage; - -pub(crate) mod shape_stream_pokemon_radio; - -pub(crate) mod shape_capture_pokemon_input; - -pub(crate) mod shape_do_nothing_output; - -pub(crate) mod shape_get_pokemon_species_input; - -pub(crate) mod shape_get_pokemon_species_output; - -pub(crate) mod shape_get_server_statistics_output; - -pub(crate) mod shape_get_storage_input; - -pub(crate) mod shape_get_storage_output; - -pub(crate) mod shape_invalid_pokeball_error; - -pub(crate) mod shape_master_ball_unsuccessful; - -pub(crate) mod shape_resource_not_found_exception; - -pub(crate) mod shape_storage_access_not_authorized; - -pub(crate) mod shape_stream_pokemon_radio_output; - -pub(crate) mod shape_throttling_error; - -pub(crate) mod shape_unsupported_region_error; - -pub(crate) mod shape_validation_exception; - -pub(crate) fn or_empty_doc(data: &[u8]) -> &[u8] { - if data.is_empty() { - b"{}" - } else { - data - } -} - -pub(crate) mod shape_capturing_payload; - -pub(crate) mod shape_flavor_text; - -pub(crate) mod shape_validation_exception_field; diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs deleted file mode 100644 index 1598292bf7e..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon.rs +++ /dev/null @@ -1,226 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_capture_pokemon_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::CapturePokemonInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - // TODO: PATCH - Changed from Into to http-body 1.x constraint for hyper 1.x compatibility - B: http_body_1_0::Body + Send + Sync + 'static, - B::Error: Into<::aws_smithy_types::body::Error> + 'static, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::capture_pokemon_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - if let Some(value) = { - Some( - crate::protocol_serde::shape_capture_pokemon_input::de_events_payload( - // TODO: PATCH - Use from_body_1_x for hyper 1.x compatibility instead of body.into() - // This works with any http-body 1.x compatible body type - &mut ::aws_smithy_types::byte_stream::ByteStream::from_body_1_x(body).into_inner(), - )?, - ) - } { - input = input.set_events(value) - } - let input_string = uri.path(); - let (input_string, (_, m1)) = - ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>( - "capture-pokemon-event", - ), - ), - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::bytes::complete::take_until("/"), - ::nom::combinator::rest, - )), - ), - ))(input_string)?; - debug_assert_eq!("", input_string); - input = - input.set_region(crate::protocol_serde::shape_capture_pokemon_input::de_region(m1)?); - input.build()? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_capture_pokemon_http_response( - #[allow(unused_variables)] output: crate::output::CapturePokemonOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let body = - ::aws_smithy_http_server::body::boxed(::aws_smithy_http_server::body::wrap_stream({ - let error_marshaller = - crate::event_stream_serde::CapturePokemonEventsErrorMarshaller::new(); - let marshaller = crate::event_stream_serde::CapturePokemonEventsMarshaller::new(); - let signer = ::aws_smithy_eventstream::frame::NoOpSigner {}; - let adapter: ::aws_smithy_http::event_stream::MessageStreamAdapter<_, _> = output - .events - .into_body_stream(marshaller, error_marshaller, signer); - adapter - })); - builder.body(body)? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_capture_pokemon_http_error( - error: &crate::error::CapturePokemonError, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - match error { - crate::error::CapturePokemonError::UnsupportedRegionError(output) => { - let payload = crate::protocol_serde::shape_unsupported_region_error::ser_unsupported_region_error_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "UnsupportedRegionError", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(500) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::CapturePokemonError::ThrottlingError(output) => { - let payload = - crate::protocol_serde::shape_throttling_error::ser_throttling_error_error( - output, - )?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ThrottlingError", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(400) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::CapturePokemonError::ValidationException(output) => { - let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ValidationException", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(400) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::CapturePokemonError::MasterBallUnsuccessful(output) => { - let payload = crate::protocol_serde::shape_master_ball_unsuccessful::ser_master_ball_unsuccessful_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "MasterBallUnsuccessful", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(500) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::CapturePokemonError::InvalidPokeballError(output) => { - let payload = crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/vnd.amazon.eventstream", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "InvalidPokeballError", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(400) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - } - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs deleted file mode 100644 index 3f101c29dc0..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capture_pokemon_input.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn de_events_payload( - body: &mut ::aws_smithy_types::body::SdkBody, -) -> std::result::Result< - ::aws_smithy_http::event_stream::Receiver< - crate::model::AttemptCapturingPokemonEvent, - crate::error::AttemptCapturingPokemonEventError, - >, - ::aws_smithy_json::deserialize::error::DeserializeError, -> { - let unmarshaller = crate::event_stream_serde::AttemptCapturingPokemonEventUnmarshaller::new(); - let body = std::mem::replace(body, ::aws_smithy_types::body::SdkBody::taken()); - Ok(::aws_smithy_http::event_stream::Receiver::new( - unmarshaller, - body, - )) -} - -pub fn de_region( - value: &str, -) -> std::result::Result< - ::std::string::String, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> { - let value = ::percent_encoding::percent_decode_str(value) - .decode_utf8()? - .into_owned(); - Ok(value) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs deleted file mode 100644 index a44b5503102..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_capturing_payload.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub(crate) fn de_capturing_payload_payload( - input: &[u8], -) -> ::std::result::Result< - crate::model::CapturingPayload, - ::aws_smithy_json::deserialize::error::DeserializeError, -> { - let mut tokens_owned = - ::aws_smithy_json::deserialize::json_token_iter(crate::protocol_serde::or_empty_doc(input)) - .peekable(); - let tokens = &mut tokens_owned; - let result = crate::protocol_serde::shape_capturing_payload::de_capturing_payload(tokens)? - .ok_or_else(|| { - ::aws_smithy_json::deserialize::error::DeserializeError::custom( - "expected payload member value", - ) - }); - if tokens.next().is_some() { - return Err( - ::aws_smithy_json::deserialize::error::DeserializeError::custom( - "found more JSON tokens after completing parsing", - ), - ); - } - result -} - -pub(crate) fn de_capturing_payload<'a, I>( - tokens: &mut ::std::iter::Peekable, -) -> ::std::result::Result< - Option, - ::aws_smithy_json::deserialize::error::DeserializeError, -> -where - I: Iterator< - Item = Result< - ::aws_smithy_json::deserialize::Token<'a>, - ::aws_smithy_json::deserialize::error::DeserializeError, - >, - >, -{ - match tokens.next().transpose()? { - Some(::aws_smithy_json::deserialize::Token::ValueNull { .. }) => Ok(None), - Some(::aws_smithy_json::deserialize::Token::StartObject { .. }) => { - #[allow(unused_mut)] - let mut builder = crate::model::capturing_payload::Builder::default(); - loop { - match tokens.next().transpose()? { - Some(::aws_smithy_json::deserialize::Token::EndObject { .. }) => break, - Some(::aws_smithy_json::deserialize::Token::ObjectKey { key, .. }) => { - match key.to_unescaped()?.as_ref() { - "name" => { - builder = builder.set_name( - ::aws_smithy_json::deserialize::token::expect_string_or_null( - tokens.next(), - )? - .map(|s| s.to_unescaped().map(|u| u.into_owned())) - .transpose()?, - ); - } - "pokeball" => { - builder = builder.set_pokeball( - ::aws_smithy_json::deserialize::token::expect_string_or_null( - tokens.next(), - )? - .map(|s| s.to_unescaped().map(|u| u.into_owned())) - .transpose()?, - ); - } - _ => ::aws_smithy_json::deserialize::token::skip_value(tokens)?, - } - } - other => { - return Err( - ::aws_smithy_json::deserialize::error::DeserializeError::custom( - format!("expected object key or end object, found: {:?}", other), - ), - ) - } - } - } - Ok(Some(builder.build())) - } - _ => Err( - ::aws_smithy_json::deserialize::error::DeserializeError::custom( - "expected start object or null", - ), - ), - } -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs deleted file mode 100644 index fd673922b0b..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_check_health.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_check_health_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::CheckHealthInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::check_health_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - ::aws_smithy_http_server::protocol::content_type_header_classifier_smithy(&headers, None)?; - input.build() - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_check_health_http_response( - #[allow(unused_variables)] output: crate::output::CheckHealthOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let payload = ""; - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - let body = ::aws_smithy_http_server::body::to_boxed(payload); - builder.body(body)? - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs deleted file mode 100644 index 067bdd12265..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_do_nothing_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::DoNothingInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::do_nothing_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - input.build() - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_do_nothing_http_response( - #[allow(unused_variables)] output: crate::output::DoNothingOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let payload = - crate::protocol_serde::shape_do_nothing_output::ser_do_nothing_output_output_output( - &output, - )?; - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - let body = ::aws_smithy_http_server::body::to_boxed(payload); - builder.body(body)? - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs deleted file mode 100644 index f3a00378542..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_do_nothing_output.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_do_nothing_output_output_output( - value: &crate::output::DoNothingOutput, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_do_nothing_output::ser_do_nothing_output_output( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_do_nothing_output_output( - #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - #[allow(unused_variables)] input: &crate::output::DoNothingOutput, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs deleted file mode 100644 index c955b79fc6e..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_flavor_text.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_flavor_text( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::model::FlavorText, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("flavorText").string(input.flavor_text.as_str()); - } - { - object.key("language").string(input.language.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs deleted file mode 100644 index 77cfa3624da..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_get_pokemon_species_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::GetPokemonSpeciesInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::get_pokemon_species_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - let input_string = uri.path(); - let (input_string, (_, m1)) = - ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>( - "pokemon-species", - ), - ), - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::bytes::complete::take_until("/"), - ::nom::combinator::rest, - )), - ), - ))(input_string)?; - debug_assert_eq!("", input_string); - input = - input.set_name(crate::protocol_serde::shape_get_pokemon_species_input::de_name(m1)?); - input.build()? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_get_pokemon_species_http_response( - #[allow(unused_variables)] output: crate::output::GetPokemonSpeciesOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let payload = - crate::protocol_serde::shape_get_pokemon_species_output::ser_get_pokemon_species_output_output_output(&output)? - ; - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - let body = ::aws_smithy_http_server::body::to_boxed(payload); - builder.body(body)? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_get_pokemon_species_http_error( - error: &crate::error::GetPokemonSpeciesError, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - match error { - crate::error::GetPokemonSpeciesError::ResourceNotFoundException(output) => { - let payload = crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ResourceNotFoundException", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(404) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::GetPokemonSpeciesError::ValidationException(output) => { - let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ValidationException", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(400) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - } - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs deleted file mode 100644 index 21f97a054fc..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_input.rs +++ /dev/null @@ -1,12 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn de_name( - value: &str, -) -> std::result::Result< - ::std::string::String, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> { - let value = ::percent_encoding::percent_decode_str(value) - .decode_utf8()? - .into_owned(); - Ok(value) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs deleted file mode 100644 index a6ace50f850..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_pokemon_species_output.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_get_pokemon_species_output_output_output( - value: &crate::output::GetPokemonSpeciesOutput, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_get_pokemon_species_output::ser_get_pokemon_species_output_output( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_get_pokemon_species_output_output( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::output::GetPokemonSpeciesOutput, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - let mut array_1 = object.key("flavorTextEntries").start_array(); - for item_2 in &input.flavor_text_entries { - { - #[allow(unused_mut)] - let mut object_3 = array_1.value().start_object(); - crate::protocol_serde::shape_flavor_text::ser_flavor_text(&mut object_3, item_2)?; - object_3.finish(); - } - } - array_1.finish(); - } - { - object.key("name").string(input.name.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs deleted file mode 100644 index 80e934069ff..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_get_server_statistics_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::GetServerStatisticsInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::get_server_statistics_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - input.build() - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_get_server_statistics_http_response( - #[allow(unused_variables)] output: crate::output::GetServerStatisticsOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let payload = - crate::protocol_serde::shape_get_server_statistics_output::ser_get_server_statistics_output_output_output(&output)? - ; - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - let body = ::aws_smithy_http_server::body::to_boxed(payload); - builder.body(body)? - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs deleted file mode 100644 index 00f4abc0aeb..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_server_statistics_output.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_get_server_statistics_output_output_output( - value: &crate::output::GetServerStatisticsOutput, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_get_server_statistics_output::ser_get_server_statistics_output_output(&mut object, value)?; - object.finish(); - Ok(out) -} - -pub fn ser_get_server_statistics_output_output( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::output::GetServerStatisticsOutput, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("calls_count").number( - #[allow(clippy::useless_conversion)] - ::aws_smithy_types::Number::NegInt((input.calls_count).into()), - ); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs deleted file mode 100644 index 0bb6dc748db..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage.rs +++ /dev/null @@ -1,163 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_get_storage_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::GetStorageInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::get_storage_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - if let Some(value) = - crate::protocol_serde::shape_get_storage_input::de_passcode_header(&headers)? - { - input = input.set_passcode(value) - } - let input_string = uri.path(); - let (input_string, (_, m1)) = - ::nom::sequence::tuple::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::bytes::complete::tag::<_, _, ::nom::error::Error<&str>>("pokedex"), - ), - ::nom::sequence::preceded( - ::nom::bytes::complete::tag("/"), - ::nom::branch::alt::<_, _, ::nom::error::Error<&str>, _>(( - ::nom::bytes::complete::take_until("/"), - ::nom::combinator::rest, - )), - ), - ))(input_string)?; - debug_assert_eq!("", input_string); - input = input.set_user(crate::protocol_serde::shape_get_storage_input::de_user(m1)?); - input.build()? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_get_storage_http_response( - #[allow(unused_variables)] output: crate::output::GetStorageOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let payload = - crate::protocol_serde::shape_get_storage_output::ser_get_storage_output_output_output( - &output, - )?; - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - let body = ::aws_smithy_http_server::body::to_boxed(payload); - builder.body(body)? - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_get_storage_http_error( - error: &crate::error::GetStorageError, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - match error { - crate::error::GetStorageError::ResourceNotFoundException(output) => { - let payload = crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ResourceNotFoundException", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(404) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::GetStorageError::StorageAccessNotAuthorized(output) => { - let payload = crate::protocol_serde::shape_storage_access_not_authorized::ser_storage_access_not_authorized_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "StorageAccessNotAuthorized", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(401) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - crate::error::GetStorageError::ValidationException(output) => { - let payload = crate::protocol_serde::shape_validation_exception::ser_validation_exception_error(output)?; - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/json", - ); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::HeaderName::from_static("x-amzn-errortype"), - "ValidationException", - ); - let content_length = payload.len(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_LENGTH, - content_length, - ); - builder - .status(400) - .body(::aws_smithy_http_server::body::to_boxed(payload))? - } - } - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs deleted file mode 100644 index 17f5204cf80..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_input.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub(crate) fn de_passcode_header( - header_map: &::aws_smithy_runtime_api::http::Headers, -) -> ::std::result::Result< - ::std::option::Option<::std::string::String>, - ::aws_smithy_http::header::ParseError, -> { - let headers = header_map.get_all("passcode"); - ::aws_smithy_http::header::one_or_none(headers) -} - -pub fn de_user( - value: &str, -) -> std::result::Result< - ::std::string::String, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> { - let value = ::percent_encoding::percent_decode_str(value) - .decode_utf8()? - .into_owned(); - Ok(value) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs deleted file mode 100644 index 9c8160fce19..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_get_storage_output.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_get_storage_output_output_output( - value: &crate::output::GetStorageOutput, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_get_storage_output::ser_get_storage_output_output( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_get_storage_output_output( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::output::GetStorageOutput, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - let mut array_1 = object.key("collection").start_array(); - for item_2 in &input.collection { - { - array_1.value().string(item_2.as_str()); - } - } - array_1.finish(); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs deleted file mode 100644 index 06e3bfdac80..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_invalid_pokeball_error.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_invalid_pokeball_error_error( - value: &crate::error::InvalidPokeballError, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_invalid_pokeball_error::ser_invalid_pokeball_error( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_invalid_pokeball_error( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::error::InvalidPokeballError, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("pokeball").string(input.pokeball.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs deleted file mode 100644 index 8edf08a0e1a..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_master_ball_unsuccessful.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_master_ball_unsuccessful_error( - value: &crate::error::MasterBallUnsuccessful, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_master_ball_unsuccessful::ser_master_ball_unsuccessful( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_master_ball_unsuccessful( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::error::MasterBallUnsuccessful, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - if let Some(var_1) = &input.message { - object.key("message").string(var_1.as_str()); - } - Ok(()) -} - -pub(crate) fn de_master_ball_unsuccessful_json_err( - value: &[u8], - mut builder: crate::error::master_ball_unsuccessful::Builder, -) -> ::std::result::Result< - crate::error::master_ball_unsuccessful::Builder, - ::aws_smithy_json::deserialize::error::DeserializeError, -> { - let mut tokens_owned = - ::aws_smithy_json::deserialize::json_token_iter(crate::protocol_serde::or_empty_doc(value)) - .peekable(); - let tokens = &mut tokens_owned; - ::aws_smithy_json::deserialize::token::expect_start_object(tokens.next())?; - loop { - match tokens.next().transpose()? { - Some(::aws_smithy_json::deserialize::Token::EndObject { .. }) => break, - Some(::aws_smithy_json::deserialize::Token::ObjectKey { key, .. }) => { - match key.to_unescaped()?.as_ref() { - "message" => { - builder = builder.set_message( - ::aws_smithy_json::deserialize::token::expect_string_or_null( - tokens.next(), - )? - .map(|s| s.to_unescaped().map(|u| u.into_owned())) - .transpose()?, - ); - } - _ => ::aws_smithy_json::deserialize::token::skip_value(tokens)?, - } - } - other => { - return Err( - ::aws_smithy_json::deserialize::error::DeserializeError::custom(format!( - "expected object key or end object, found: {:?}", - other - )), - ) - } - } - } - if tokens.next().is_some() { - return Err( - ::aws_smithy_json::deserialize::error::DeserializeError::custom( - "found more JSON tokens after completing parsing", - ), - ); - } - Ok(builder) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs deleted file mode 100644 index 34b63fe69c7..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_resource_not_found_exception.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_resource_not_found_exception_error( - value: &crate::error::ResourceNotFoundException, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_resource_not_found_exception::ser_resource_not_found_exception( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_resource_not_found_exception( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::error::ResourceNotFoundException, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("message").string(input.message.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs deleted file mode 100644 index 8572989d52e..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_storage_access_not_authorized.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_storage_access_not_authorized_error( - value: &crate::error::StorageAccessNotAuthorized, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_storage_access_not_authorized::ser_storage_access_not_authorized( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_storage_access_not_authorized( - #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - #[allow(unused_variables)] input: &crate::error::StorageAccessNotAuthorized, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs deleted file mode 100644 index 1e7c0ff13cb..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -#[allow(clippy::unnecessary_wraps)] -pub async fn de_stream_pokemon_radio_http_request( - #[allow(unused_variables)] request: ::http::Request, -) -> std::result::Result< - crate::input::StreamPokemonRadioInput, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection, -> -where - B: ::aws_smithy_http_server::body::HttpBody + Send, - B::Data: Send, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::RequestRejection: - From<::Error>, -{ - Ok({ - #[allow(unused_mut)] - let mut input = crate::input::stream_pokemon_radio_input::Builder::default(); - #[allow(unused_variables)] - let ::aws_smithy_runtime_api::http::RequestParts { - uri, headers, body, .. - } = ::aws_smithy_runtime_api::http::Request::try_from(request)?.into_parts(); - ::aws_smithy_http_server::protocol::content_type_header_classifier_smithy(&headers, None)?; - input.build() - }) -} - -#[allow(clippy::unnecessary_wraps)] -pub fn ser_stream_pokemon_radio_http_response( - #[allow(unused_variables)] output: crate::output::StreamPokemonRadioOutput, -) -> std::result::Result< - ::aws_smithy_http_server::response::Response, - ::aws_smithy_http_server::protocol::rest_json_1::rejection::ResponseRejection, -> { - Ok({ - #[allow(unused_mut)] - let mut builder = ::http::Response::builder(); - builder = ::aws_smithy_http::header::set_response_header_if_absent( - builder, - ::http::header::CONTENT_TYPE, - "application/octet-stream", - ); - let http_status: u16 = 200; - builder = builder.status(http_status); - let body = ::aws_smithy_http_server::body::boxed(::aws_smithy_http_server::body::wrap_stream( - ::aws_smithy_http::futures_stream_adapter::FuturesStreamCompatByteStream::new( - crate::protocol_serde::shape_stream_pokemon_radio_output::ser_data_http_payload( output.data)? - ) - )); - builder.body(body)? - }) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs deleted file mode 100644 index 55587893101..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_stream_pokemon_radio_output.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_data_http_payload( - payload: ::aws_smithy_types::byte_stream::ByteStream, -) -> ::std::result::Result< - ::aws_smithy_types::byte_stream::ByteStream, - ::aws_smithy_types::error::operation::BuildError, -> { - Ok(payload) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs deleted file mode 100644 index b254155c2a3..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_throttling_error.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_throttling_error_error( - value: &crate::error::ThrottlingError, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_throttling_error::ser_throttling_error(&mut object, value)?; - object.finish(); - Ok(out) -} - -pub fn ser_throttling_error( - #[allow(unused_variables)] object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - #[allow(unused_variables)] input: &crate::error::ThrottlingError, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs deleted file mode 100644 index 50fe15cc003..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_unsupported_region_error.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_unsupported_region_error_error( - value: &crate::error::UnsupportedRegionError, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_unsupported_region_error::ser_unsupported_region_error( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_unsupported_region_error( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::error::UnsupportedRegionError, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("region").string(input.region.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs deleted file mode 100644 index d27dafb8b4a..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_validation_exception_error( - value: &crate::error::ValidationException, -) -> ::std::result::Result { - let mut out = ::std::string::String::new(); - let mut object = ::aws_smithy_json::serialize::JsonObjectWriter::new(&mut out); - crate::protocol_serde::shape_validation_exception::ser_validation_exception( - &mut object, - value, - )?; - object.finish(); - Ok(out) -} - -pub fn ser_validation_exception( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::error::ValidationException, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - if let Some(var_1) = &input.field_list { - let mut array_2 = object.key("fieldList").start_array(); - for item_3 in var_1 { - { - #[allow(unused_mut)] - let mut object_4 = array_2.value().start_object(); - crate::protocol_serde::shape_validation_exception_field::ser_validation_exception_field(&mut object_4, item_3)?; - object_4.finish(); - } - } - array_2.finish(); - } - { - object.key("message").string(input.message.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs b/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs deleted file mode 100644 index 3321330af65..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/protocol_serde/shape_validation_exception_field.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub fn ser_validation_exception_field( - object: &mut ::aws_smithy_json::serialize::JsonObjectWriter, - input: &crate::model::ValidationExceptionField, -) -> ::std::result::Result<(), ::aws_smithy_types::error::operation::SerializationError> { - { - object.key("path").string(input.path.as_str()); - } - { - object.key("message").string(input.message.as_str()); - } - Ok(()) -} diff --git a/examples/pokemon-service-server-skd-patch/src/service.rs b/examples/pokemon-service-server-skd-patch/src/service.rs deleted file mode 100644 index bbaaa11f938..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/service.rs +++ /dev/null @@ -1,1963 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -/// The service builder for [`PokemonService`]. -/// -/// Constructed via [`PokemonService::builder`]. -pub struct PokemonServiceBuilder { - capture_pokemon: Option<::aws_smithy_http_server::routing::Route>, - check_health: Option<::aws_smithy_http_server::routing::Route>, - do_nothing: Option<::aws_smithy_http_server::routing::Route>, - get_pokemon_species: Option<::aws_smithy_http_server::routing::Route>, - get_server_statistics: Option<::aws_smithy_http_server::routing::Route>, - get_storage: Option<::aws_smithy_http_server::routing::Route>, - stream_pokemon_radio: Option<::aws_smithy_http_server::routing::Route>, - layer: L, - http_plugin: HttpPl, - model_plugin: ModelPl, -} - -impl PokemonServiceBuilder { - /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::CapturePokemonInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .capture_pokemon(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn capture_pokemon(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::CapturePokemon::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.capture_pokemon_custom(svc) - } - - /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::CapturePokemonInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .capture_pokemon_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn capture_pokemon_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CapturePokemon, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::CapturePokemon::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.capture_pokemon_custom(svc) - } - - /// Sets the [`CapturePokemon`](crate::operation_shape::CapturePokemon) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn capture_pokemon_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.capture_pokemon = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::CheckHealthInput) -> output::CheckHealthOutput { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .check_health(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn check_health(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::CheckHealth::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.check_health_custom(svc) - } - - /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::CheckHealthInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .check_health_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn check_health_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::CheckHealth, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::CheckHealth::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.check_health_custom(svc) - } - - /// Sets the [`CheckHealth`](crate::operation_shape::CheckHealth) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn check_health_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.check_health = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::DoNothingInput) -> output::DoNothingOutput { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .do_nothing(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn do_nothing(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::DoNothing::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.do_nothing_custom(svc) - } - - /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::DoNothingInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .do_nothing_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn do_nothing_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::DoNothing, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::DoNothing::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.do_nothing_custom(svc) - } - - /// Sets the [`DoNothing`](crate::operation_shape::DoNothing) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn do_nothing_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.do_nothing = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetPokemonSpeciesInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .get_pokemon_species(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_pokemon_species(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetPokemonSpecies::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_pokemon_species_custom(svc) - } - - /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetPokemonSpeciesInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .get_pokemon_species_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_pokemon_species_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetPokemonSpecies, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetPokemonSpecies::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_pokemon_species_custom(svc) - } - - /// Sets the [`GetPokemonSpecies`](crate::operation_shape::GetPokemonSpecies) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn get_pokemon_species_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.get_pokemon_species = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetServerStatisticsInput) -> output::GetServerStatisticsOutput { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .get_server_statistics(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_server_statistics(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetServerStatistics::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_server_statistics_custom(svc) - } - - /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetServerStatisticsInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .get_server_statistics_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_server_statistics_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetServerStatistics, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetServerStatistics::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_server_statistics_custom(svc) - } - - /// Sets the [`GetServerStatistics`](crate::operation_shape::GetServerStatistics) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn get_server_statistics_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.get_server_statistics = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetStorageInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .get_storage(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_storage(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetStorage::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_storage_custom(svc) - } - - /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::GetStorageInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .get_storage_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn get_storage_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::GetStorage, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::GetStorage::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.get_storage_custom(svc) - } - - /// Sets the [`GetStorage`](crate::operation_shape::GetStorage) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn get_storage_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.get_storage = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } - - /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::StreamPokemonRadioInput) -> output::StreamPokemonRadioOutput { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let app = PokemonService::builder(config) - /// .stream_pokemon_radio(handler) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn stream_pokemon_radio(self, handler: HandlerType) -> Self - where - HandlerType: ::aws_smithy_http_server::operation::Handler, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ::aws_smithy_http_server::operation::IntoService - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::StreamPokemonRadio::from_handler(handler); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.stream_pokemon_radio_custom(svc) - } - - /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) operation. - /// - /// This should be an async function satisfying the [`Handler`](::aws_smithy_http_server::operation::Handler) trait. - /// See the [operation module documentation](::aws_smithy_http_server::operation) for more information. - /// - /// # Example - /// - /// ```no_run - /// use pokemon_service_server_sdk::{PokemonService, PokemonServiceConfig}; - /// - /// use pokemon_service_server_sdk::{input, output, error}; - /// - /// async fn handler(input: input::StreamPokemonRadioInput) -> Result { - /// todo!() - /// } - /// - /// let config = PokemonServiceConfig::builder().build(); - /// let svc = ::tower::util::service_fn(handler); - /// let app = PokemonService::builder(config) - /// .stream_pokemon_radio_service(svc) - /// /* Set other handlers */ - /// .build() - /// .unwrap(); - /// # let app: PokemonService<::aws_smithy_http_server::routing::RoutingService<::aws_smithy_http_server::protocol::rest::router::RestRouter<::aws_smithy_http_server::routing::Route>, ::aws_smithy_http_server::protocol::rest_json_1::RestJson1>> = app; - /// ``` - /// - pub fn stream_pokemon_radio_service(self, service: S) -> Self - where - S: ::aws_smithy_http_server::operation::OperationService, - - ModelPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ::aws_smithy_http_server::operation::Normalize - >, - ::aws_smithy_http_server::operation::UpgradePlugin::: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ModelPl::Output - >, - HttpPl: ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - < - ::aws_smithy_http_server::operation::UpgradePlugin:: - as ::aws_smithy_http_server::plugin::Plugin< - PokemonService, - crate::operation_shape::StreamPokemonRadio, - ModelPl::Output - > - >::Output - >, - - HttpPl::Output: ::tower::Service<::http::Request, Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, Error = ::std::convert::Infallible> + Clone + Send + 'static, - >>::Future: Send + 'static, - - { - use ::aws_smithy_http_server::operation::OperationShapeExt; - use ::aws_smithy_http_server::plugin::Plugin; - let svc = crate::operation_shape::StreamPokemonRadio::from_service(service); - let svc = self.model_plugin.apply(svc); - let svc = ::aws_smithy_http_server::operation::UpgradePlugin::::new() - .apply(svc); - let svc = self.http_plugin.apply(svc); - self.stream_pokemon_radio_custom(svc) - } - - /// Sets the [`StreamPokemonRadio`](crate::operation_shape::StreamPokemonRadio) to a custom [`Service`](tower::Service). - /// not constrained by the Smithy contract. - fn stream_pokemon_radio_custom(mut self, svc: S) -> Self - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = ::std::convert::Infallible, - > + Clone - + Send - + 'static, - S::Future: Send + 'static, - { - self.stream_pokemon_radio = Some(::aws_smithy_http_server::routing::Route::new(svc)); - self - } -} - -impl PokemonServiceBuilder { - /// Constructs a [`PokemonService`] from the arguments provided to the builder. - /// - /// Forgetting to register a handler for one or more operations will result in an error. - /// - /// Check out [`PokemonServiceBuilder::build_unchecked`] if you'd prefer the service to return status code 500 when an - /// unspecified route is requested. - pub fn build( - self, - ) -> ::std::result::Result< - PokemonService< - ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, - >, - MissingOperationsError, - > - where - L: ::tower::Layer<::aws_smithy_http_server::routing::Route>, - { - let router = { - use ::aws_smithy_http_server::operation::OperationShape; - let mut missing_operation_names = std::collections::HashMap::new(); - if self.capture_pokemon.is_none() { - missing_operation_names.insert( - crate::operation_shape::CapturePokemon::ID, - ".capture_pokemon()", - ); - } - if self.check_health.is_none() { - missing_operation_names - .insert(crate::operation_shape::CheckHealth::ID, ".check_health()"); - } - if self.do_nothing.is_none() { - missing_operation_names - .insert(crate::operation_shape::DoNothing::ID, ".do_nothing()"); - } - if self.get_pokemon_species.is_none() { - missing_operation_names.insert( - crate::operation_shape::GetPokemonSpecies::ID, - ".get_pokemon_species()", - ); - } - if self.get_server_statistics.is_none() { - missing_operation_names.insert( - crate::operation_shape::GetServerStatistics::ID, - ".get_server_statistics()", - ); - } - if self.get_storage.is_none() { - missing_operation_names - .insert(crate::operation_shape::GetStorage::ID, ".get_storage()"); - } - if self.stream_pokemon_radio.is_none() { - missing_operation_names.insert( - crate::operation_shape::StreamPokemonRadio::ID, - ".stream_pokemon_radio()", - ); - } - if !missing_operation_names.is_empty() { - return Err(MissingOperationsError { - operation_names2setter_methods: missing_operation_names, - }); - } - let unexpected_error_msg = "this should never panic since we are supposed to check beforehand that a handler has been registered for this operation; please file a bug report under https://github.com/smithy-lang/smithy-rs/issues"; - - ::aws_smithy_http_server::protocol::rest::router::RestRouter::from_iter([ - ( - request_specs::capture_pokemon(), - self.capture_pokemon.expect(unexpected_error_msg), - ), - ( - request_specs::check_health(), - self.check_health.expect(unexpected_error_msg), - ), - ( - request_specs::do_nothing(), - self.do_nothing.expect(unexpected_error_msg), - ), - ( - request_specs::get_pokemon_species(), - self.get_pokemon_species.expect(unexpected_error_msg), - ), - ( - request_specs::get_server_statistics(), - self.get_server_statistics.expect(unexpected_error_msg), - ), - ( - request_specs::get_storage(), - self.get_storage.expect(unexpected_error_msg), - ), - ( - request_specs::stream_pokemon_radio(), - self.stream_pokemon_radio.expect(unexpected_error_msg), - ), - ]) - }; - let svc = ::aws_smithy_http_server::routing::RoutingService::new(router); - let svc = svc.map(|s| s.layer(self.layer)); - Ok(PokemonService { svc }) - } - - /// Constructs a [`PokemonService`] from the arguments provided to the builder. - /// Operations without a handler default to returning 500 Internal Server Error to the caller. - /// - /// Check out [`PokemonServiceBuilder::build`] if you'd prefer the builder to fail if one or more operations do - /// not have a registered handler. - pub fn build_unchecked(self) -> PokemonService - where - Body: Send + 'static, - L: ::tower::Layer< - ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter< - ::aws_smithy_http_server::routing::Route, - >, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, - >, - { - let router = ::aws_smithy_http_server::protocol::rest::router::RestRouter::from_iter([ - ( - request_specs::capture_pokemon(), - self.capture_pokemon.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::check_health(), - self.check_health.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::do_nothing(), - self.do_nothing.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::get_pokemon_species(), - self.get_pokemon_species.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::get_server_statistics(), - self.get_server_statistics.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::get_storage(), - self.get_storage.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ( - request_specs::stream_pokemon_radio(), - self.stream_pokemon_radio.unwrap_or_else(|| { - let svc = ::aws_smithy_http_server::operation::MissingFailure::< - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >::default(); - ::aws_smithy_http_server::routing::Route::new(svc) - }), - ), - ]); - let svc = self - .layer - .layer(::aws_smithy_http_server::routing::RoutingService::new( - router, - )); - PokemonService { svc } - } -} - -/// The error encountered when calling the [`PokemonServiceBuilder::build`] method if one or more operation handlers are not -/// specified. -#[derive(Debug)] -pub struct MissingOperationsError { - operation_names2setter_methods: - std::collections::HashMap<::aws_smithy_http_server::shape_id::ShapeId, &'static str>, -} - -impl std::fmt::Display for MissingOperationsError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "You must specify a handler for all operations attached to `PokemonService`.\n\ - We are missing handlers for the following operations:\n", - )?; - for operation_name in self.operation_names2setter_methods.keys() { - writeln!(f, "- {}", operation_name.absolute())?; - } - - writeln!(f, "\nUse the dedicated methods on `PokemonServiceBuilder` to register the missing handlers:")?; - for setter_name in self.operation_names2setter_methods.values() { - writeln!(f, "- {}", setter_name)?; - } - Ok(()) - } -} - -impl std::error::Error for MissingOperationsError {} - -mod request_specs { - pub(super) fn capture_pokemon() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec - { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::POST, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("capture-pokemon-event")), - ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn check_health() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("ping")), -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn do_nothing() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("do-nothing")), -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn get_pokemon_species( - ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("pokemon-species")), - ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn get_server_statistics( - ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("stats")), -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn get_storage() -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("pokedex")), - ::aws_smithy_http_server::routing::request_spec::PathSegment::Label, -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } - pub(super) fn stream_pokemon_radio( - ) -> ::aws_smithy_http_server::routing::request_spec::RequestSpec { - ::aws_smithy_http_server::routing::request_spec::RequestSpec::new( - ::http::Method::GET, - ::aws_smithy_http_server::routing::request_spec::UriSpec::new( - ::aws_smithy_http_server::routing::request_spec::PathAndQuerySpec::new( - ::aws_smithy_http_server::routing::request_spec::PathSpec::from_vector_unchecked(vec![ - ::aws_smithy_http_server::routing::request_spec::PathSegment::Literal(String::from("radio")), -]), - ::aws_smithy_http_server::routing::request_spec::QuerySpec::from_vector_unchecked(vec![ -]) - ) - ), - ) - } -} - -/// The Pokémon Service allows you to retrieve information about Pokémon species. -/// -/// See the [root](crate) documentation for more information. -#[derive(Clone)] -pub struct PokemonService< - S = ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter< - ::aws_smithy_http_server::routing::Route<::aws_smithy_http_server::body::BoxBody>, - >, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, -> { - // This is the router wrapped by layers. - svc: S, -} - -impl PokemonService<()> { - /// Constructs a builder for [`PokemonService`]. - /// You must specify a configuration object holding any plugins and layers that should be applied - /// to the operations in this service. - pub fn builder< - Body, - L, - HttpPl: ::aws_smithy_http_server::plugin::HttpMarker, - ModelPl: ::aws_smithy_http_server::plugin::ModelMarker, - >( - config: PokemonServiceConfig, - ) -> PokemonServiceBuilder { - PokemonServiceBuilder { - capture_pokemon: None, - check_health: None, - do_nothing: None, - get_pokemon_species: None, - get_server_statistics: None, - get_storage: None, - stream_pokemon_radio: None, - layer: config.layers, - http_plugin: config.http_plugins, - model_plugin: config.model_plugins, - } - } - - /// Constructs a builder for [`PokemonService`]. - /// You must specify what plugins should be applied to the operations in this service. - /// - /// Use [`PokemonService::builder_without_plugins`] if you don't need to apply plugins. - /// - /// Check out [`HttpPlugins`](::aws_smithy_http_server::plugin::HttpPlugins) and - /// [`ModelPlugins`](::aws_smithy_http_server::plugin::ModelPlugins) if you need to apply - /// multiple plugins. - #[deprecated( - since = "0.57.0", - note = "please use the `builder` constructor and register plugins on the `PokemonServiceConfig` object instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" - )] - pub fn builder_with_plugins< - Body, - HttpPl: ::aws_smithy_http_server::plugin::HttpMarker, - ModelPl: ::aws_smithy_http_server::plugin::ModelMarker, - >( - http_plugin: HttpPl, - model_plugin: ModelPl, - ) -> PokemonServiceBuilder { - PokemonServiceBuilder { - capture_pokemon: None, - check_health: None, - do_nothing: None, - get_pokemon_species: None, - get_server_statistics: None, - get_storage: None, - stream_pokemon_radio: None, - layer: ::tower::layer::util::Identity::new(), - http_plugin, - model_plugin, - } - } - - /// Constructs a builder for [`PokemonService`]. - /// - /// Use [`PokemonService::builder_with_plugins`] if you need to specify plugins. - #[deprecated( - since = "0.57.0", - note = "please use the `builder` constructor instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" - )] - pub fn builder_without_plugins() -> PokemonServiceBuilder< - Body, - ::tower::layer::util::Identity, - ::aws_smithy_http_server::plugin::IdentityPlugin, - ::aws_smithy_http_server::plugin::IdentityPlugin, - > { - Self::builder_with_plugins( - ::aws_smithy_http_server::plugin::IdentityPlugin, - ::aws_smithy_http_server::plugin::IdentityPlugin, - ) - } -} - -impl PokemonService { - /// Converts [`PokemonService`] into a [`MakeService`](tower::make::MakeService) with [`ConnectInfo`](::aws_smithy_http_server::request::connect_info::ConnectInfo). - pub fn into_make_service_with_connect_info( - self, - ) -> ::aws_smithy_http_server::routing::IntoMakeServiceWithConnectInfo { - ::aws_smithy_http_server::routing::IntoMakeServiceWithConnectInfo::new(self) - } -} - -impl - PokemonService< - ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, - > -{ - /// Applies a [`Layer`](::tower::Layer) uniformly to all routes. - #[deprecated( - since = "0.57.0", - note = "please add layers to the `PokemonServiceConfig` object instead; see https://github.com/smithy-lang/smithy-rs/discussions/3096" - )] - pub fn layer( - self, - layer: &L, - ) -> PokemonService< - ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, - > - where - L: ::tower::Layer, - { - PokemonService { - svc: self.svc.map(|s| s.layer(layer)), - } - } - - /// Applies [`Route::new`](::aws_smithy_http_server::routing::Route::new) to all routes. - /// - /// This has the effect of erasing all types accumulated via layers. - pub fn boxed( - self, - ) -> PokemonService< - ::aws_smithy_http_server::routing::RoutingService< - ::aws_smithy_http_server::protocol::rest::router::RestRouter< - ::aws_smithy_http_server::routing::Route, - >, - ::aws_smithy_http_server::protocol::rest_json_1::RestJson1, - >, - > - where - S: ::tower::Service< - ::http::Request, - Response = ::http::Response<::aws_smithy_http_server::body::BoxBody>, - Error = std::convert::Infallible, - >, - S: Clone + Send + 'static, - S::Future: Send + 'static, - { - self.layer(&::tower::layer::layer_fn( - ::aws_smithy_http_server::routing::Route::new, - )) - } -} - -impl ::tower::Service for PokemonService -where - S: ::tower::Service, -{ - type Response = S::Response; - type Error = S::Error; - type Future = S::Future; - - fn poll_ready( - &mut self, - cx: &mut std::task::Context, - ) -> std::task::Poll<::std::result::Result<(), Self::Error>> { - self.svc.poll_ready(cx) - } - - fn call(&mut self, request: R) -> Self::Future { - self.svc.call(request) - } -} - -/// An enumeration of all [operations](https://smithy.io/2.0/spec/service-types.html#operation) in PokemonService. -#[allow(clippy::enum_variant_names)] -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum Operation { - CapturePokemon, - CheckHealth, - DoNothing, - GetPokemonSpecies, - GetServerStatistics, - GetStorage, - StreamPokemonRadio, -} - -impl Operation { - /// Returns the [operations](https://smithy.io/2.0/spec/service-types.html#operation) [`ShapeId`](::aws_smithy_http_server::shape_id::ShapeId). - pub fn shape_id(&self) -> ::aws_smithy_http_server::shape_id::ShapeId { - match self { - Operation::CapturePokemon => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#CapturePokemon", - "com.aws.example", - "CapturePokemon", - ), - Operation::CheckHealth => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#CheckHealth", - "com.aws.example", - "CheckHealth", - ), - Operation::DoNothing => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#DoNothing", - "com.aws.example", - "DoNothing", - ), - Operation::GetPokemonSpecies => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetPokemonSpecies", - "com.aws.example", - "GetPokemonSpecies", - ), - Operation::GetServerStatistics => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetServerStatistics", - "com.aws.example", - "GetServerStatistics", - ), - Operation::GetStorage => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#GetStorage", - "com.aws.example", - "GetStorage", - ), - Operation::StreamPokemonRadio => ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#StreamPokemonRadio", - "com.aws.example", - "StreamPokemonRadio", - ), - } - } -} -impl ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::CapturePokemon; -} -impl ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::CheckHealth; -} -impl ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::DoNothing; -} -impl - ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::GetPokemonSpecies; -} -impl - ::aws_smithy_http_server::service::ContainsOperation< - crate::operation_shape::GetServerStatistics, - > for PokemonService -{ - const VALUE: Operation = Operation::GetServerStatistics; -} -impl ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::GetStorage; -} -impl - ::aws_smithy_http_server::service::ContainsOperation - for PokemonService -{ - const VALUE: Operation = Operation::StreamPokemonRadio; -} - -impl ::aws_smithy_http_server::service::ServiceShape for PokemonService { - const ID: ::aws_smithy_http_server::shape_id::ShapeId = - ::aws_smithy_http_server::shape_id::ShapeId::new( - "com.aws.example#PokemonService", - "com.aws.example", - "PokemonService", - ); - - const VERSION: Option<&'static str> = Some("2024-03-18"); - - type Protocol = ::aws_smithy_http_server::protocol::rest_json_1::RestJson1; - - type Operations = Operation; -} -/// Configuration for the [`PokemonService`]. This is the central place where to register and -/// configure [`::tower::Layer`]s, HTTP plugins, and model plugins. -/// -/// ```rust,no_run -/// # use pokemon_service_server_sdk::PokemonServiceConfig; -/// # use ::aws_smithy_http_server::plugin::IdentityPlugin; -/// # use ::tower::layer::util::Identity; -/// # let authentication_plugin = IdentityPlugin; -/// # let authorization_plugin = IdentityPlugin; -/// # let server_request_id_provider_layer = Identity::new(); -/// let config = PokemonServiceConfig::builder() -/// // Layers get executed first... -/// .layer(server_request_id_provider_layer) -/// // ...then HTTP plugins... -/// .http_plugin(authentication_plugin) -/// // ...and right after deserialization, model plugins. -/// .model_plugin(authorization_plugin) -/// .build(); -/// ``` -/// -/// See the [`plugin`] system for details. -/// -/// [`plugin`]: ::aws_smithy_http_server::plugin -#[derive(::std::fmt::Debug)] -pub struct PokemonServiceConfig { - layers: L, - http_plugins: H, - model_plugins: M, -} - -impl PokemonServiceConfig<(), (), ()> { - /// Returns a builder to construct the configuration. - pub fn builder() -> PokemonServiceConfigBuilder< - ::tower::layer::util::Identity, - ::aws_smithy_http_server::plugin::IdentityPlugin, - ::aws_smithy_http_server::plugin::IdentityPlugin, - > { - PokemonServiceConfigBuilder { - layers: ::tower::layer::util::Identity::new(), - http_plugins: ::aws_smithy_http_server::plugin::IdentityPlugin, - model_plugins: ::aws_smithy_http_server::plugin::IdentityPlugin, - } - } -} - -/// Builder returned by [`PokemonServiceConfig::builder()`]. -#[derive(::std::fmt::Debug)] -pub struct PokemonServiceConfigBuilder { - pub(crate) layers: L, - pub(crate) http_plugins: H, - pub(crate) model_plugins: M, -} - -impl PokemonServiceConfigBuilder { - /// Add a [`::tower::Layer`] to the service. - pub fn layer( - self, - layer: NewLayer, - ) -> PokemonServiceConfigBuilder<::tower::layer::util::Stack, H, M> { - PokemonServiceConfigBuilder { - layers: ::tower::layer::util::Stack::new(layer, self.layers), - http_plugins: self.http_plugins, - model_plugins: self.model_plugins, - } - } - - /// Add a HTTP [plugin] to the service. - /// - /// [plugin]: ::aws_smithy_http_server::plugin - // We eagerly require `NewPlugin: HttpMarker`, despite not really needing it, because compiler - // errors get _substantially_ better if the user makes a mistake. - pub fn http_plugin( - self, - http_plugin: NewPlugin, - ) -> PokemonServiceConfigBuilder< - L, - ::aws_smithy_http_server::plugin::PluginStack, - M, - > { - PokemonServiceConfigBuilder { - layers: self.layers, - http_plugins: ::aws_smithy_http_server::plugin::PluginStack::new( - http_plugin, - self.http_plugins, - ), - model_plugins: self.model_plugins, - } - } - - /// Add a model [plugin] to the service. - /// - /// [plugin]: ::aws_smithy_http_server::plugin - // We eagerly require `NewPlugin: ModelMarker`, despite not really needing it, because compiler - // errors get _substantially_ better if the user makes a mistake. - pub fn model_plugin( - self, - model_plugin: NewPlugin, - ) -> PokemonServiceConfigBuilder< - L, - H, - ::aws_smithy_http_server::plugin::PluginStack, - > { - PokemonServiceConfigBuilder { - layers: self.layers, - http_plugins: self.http_plugins, - model_plugins: ::aws_smithy_http_server::plugin::PluginStack::new( - model_plugin, - self.model_plugins, - ), - } - } - - /// Build the configuration. - pub fn build(self) -> super::PokemonServiceConfig { - super::PokemonServiceConfig { - layers: self.layers, - http_plugins: self.http_plugins, - model_plugins: self.model_plugins, - } - } -} -/// A macro to help with scoping [plugins](crate::server::plugin) to a subset of all operations. -/// -/// In contrast to [`crate::server::scope`](crate::server::scope), this macro has knowledge -/// of the service and any operations _not_ specified will be placed in the opposing group. -/// -/// # Example -/// -/// ```rust -/// scope! { -/// /// Includes [`CapturePokemon`], excluding all other operations. -/// struct ScopeA { -/// includes: [CapturePokemon] -/// } -/// } -/// -/// scope! { -/// /// Excludes [`CapturePokemon`], excluding all other operations. -/// struct ScopeB { -/// excludes: [CapturePokemon] -/// } -/// } -/// -/// # use pokemon_service_server_sdk::server::plugin::{Plugin, Scoped}; -/// # use pokemon_service_server_sdk::scope; -/// # struct MockPlugin; -/// # impl Plugin for MockPlugin { type Output = u32; fn apply(&self, input: T) -> u32 { 3 } } -/// # let scoped_a = Scoped::new::(MockPlugin); -/// # let scoped_b = Scoped::new::(MockPlugin); -/// # let a = Plugin::<(), pokemon_service_server_sdk::operation_shape::CapturePokemon, u64>::apply(&scoped_a, 6); -/// # let b = Plugin::<(), pokemon_service_server_sdk::operation_shape::CapturePokemon, u64>::apply(&scoped_b, 6); -/// # assert_eq!(a, 3_u32); -/// # assert_eq!(b, 6_u64); -/// ``` -#[macro_export] -macro_rules! scope { - // Completed, render impls - (@ $ name: ident, $ contains: ident () ($($ temp: ident)*) ($($ not_member: ident)*)) => { - $( - impl $ crate::server::plugin::scoped::Membership<$ temp> for $ name { - type Contains = $ crate::server::plugin::scoped::$ contains; - } - )* - $( - impl $ crate::server::plugin::scoped::Membership<$ not_member> for $ name { - type Contains = $ crate::server::plugin::scoped::$ contains; - } - )* - }; - // All `not_member`s exhausted, move `temp` into `not_member` - (@ $ name: ident, $ contains: ident ($($ member: ident)*) ($($ temp: ident)*) ()) => { - scope! { @ $ name, $ contains ($($ member)*) () ($($ temp)*) } - }; - - // CapturePokemon match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (CapturePokemon $($ member: ident)*) ($($ temp: ident)*) (CapturePokemon $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // CapturePokemon match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (CapturePokemon $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (CapturePokemon $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // CheckHealth match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (CheckHealth $($ member: ident)*) ($($ temp: ident)*) (CheckHealth $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // CheckHealth match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (CheckHealth $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (CheckHealth $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // DoNothing match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (DoNothing $($ member: ident)*) ($($ temp: ident)*) (DoNothing $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // DoNothing match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (DoNothing $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (DoNothing $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // GetPokemonSpecies match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (GetPokemonSpecies $($ member: ident)*) ($($ temp: ident)*) (GetPokemonSpecies $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // GetPokemonSpecies match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (GetPokemonSpecies $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (GetPokemonSpecies $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // GetServerStatistics match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (GetServerStatistics $($ member: ident)*) ($($ temp: ident)*) (GetServerStatistics $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // GetServerStatistics match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (GetServerStatistics $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (GetServerStatistics $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // GetStorage match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (GetStorage $($ member: ident)*) ($($ temp: ident)*) (GetStorage $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // GetStorage match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (GetStorage $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (GetStorage $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - // StreamPokemonRadio match found, pop from both `member` and `not_member` - (@ $ name: ident, $ contains: ident (StreamPokemonRadio $($ member: ident)*) ($($ temp: ident)*) (StreamPokemonRadio $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains ($($ member)*) ($($ temp)*) ($($ not_member)*) } - }; - // StreamPokemonRadio match not found, pop from `not_member` into `temp` stack - (@ $ name: ident, $ contains: ident (StreamPokemonRadio $($ member: ident)*) ($($ temp: ident)*) ($ other: ident $($ not_member: ident)*)) => { - scope! { @ $ name, $ contains (StreamPokemonRadio $($ member)*) ($ other $($ temp)*) ($($ not_member)*) } - }; - - ( - $(#[$ attrs:meta])* - $ vis:vis struct $ name:ident { - includes: [$($ include:ident),*] - } - ) => { - use $ crate::operation_shape::*; - $ crate::server::scope! { - $(#[$ attrs])* - $ vis struct $ name { - includes: [$($ include),*], - excludes: [] - } - } - scope! { @ $ name, False ($($ include)*) () (CapturePokemon CheckHealth DoNothing GetPokemonSpecies GetServerStatistics GetStorage StreamPokemonRadio) } - }; - ( - $(#[$ attrs:meta])* - $ vis:vis struct $ name:ident { - excludes: [$($ exclude:ident),*] - } - ) => { - use $ crate::operation_shape::*; - - $ crate::server::scope! { - $(#[$ attrs])* - $ vis struct $ name { - includes: [], - excludes: [$($ exclude),*] - } - } - scope! { @ $ name, True ($($ exclude)*) () (CapturePokemon CheckHealth DoNothing GetPokemonSpecies GetServerStatistics GetStorage StreamPokemonRadio) } - }; - } diff --git a/examples/pokemon-service-server-skd-patch/src/types.rs b/examples/pokemon-service-server-skd-patch/src/types.rs deleted file mode 100644 index 0dc25aa3b50..00000000000 --- a/examples/pokemon-service-server-skd-patch/src/types.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT. -pub use ::aws_smithy_types::body::SdkBody; -pub use ::aws_smithy_types::byte_stream::error::Error as ByteStreamError; -pub use ::aws_smithy_types::byte_stream::AggregatedBytes; -pub use ::aws_smithy_types::byte_stream::ByteStream; -#[cfg(feature = "rt-tokio")] -pub use ::aws_smithy_types::byte_stream::FsBuilder; -#[cfg(feature = "rt-tokio")] -pub use ::aws_smithy_types::byte_stream::Length; -pub use ::aws_smithy_types::date_time::Format as DateTimeFormat; -pub use ::aws_smithy_types::error::display::DisplayErrorContext; -pub use ::aws_smithy_types::Blob; -pub use ::aws_smithy_types::DateTime; diff --git a/examples/upgrade-http1x.md b/examples/upgrade-http1x.md index 1fa9dddf5e1..4b7281e629c 100644 --- a/examples/upgrade-http1x.md +++ b/examples/upgrade-http1x.md @@ -23,11 +23,9 @@ The http and hyper crates have released major version updates (http@1.x and hype - http: 0.2.x → 1.x - hyper: 0.14.x → 1.x - New hyper-util crate for additional utilities -- aws-smithy-http-server replaces aws-smithy-legacy-http-server ## Why Upgrade? -- **Better Performance**: Hyper 1.x has improved performance and reduced allocations - **Improved API**: More ergonomic and safer APIs in both http and hyper - **Active Support**: Future updates and bug fixes will target 1.x versions - **Ecosystem Alignment**: New libraries are targeting http@1.x and hyper@1.x @@ -42,11 +40,6 @@ The http and hyper crates have released major version updates (http@1.x and hype 3. **Gradual Migration**: Consider migrating one service at a time 4. **Legacy Examples**: The `examples/legacy/` directory contains fully working http@0.2 examples for reference -**Compatibility:** -- Minimum Rust version: Check your generated SDK's rust-toolchain.toml -- Tokio runtime: Still compatible with tokio 1.x -- Tower middleware: Compatible with tower 0.4 - ## Dependency Updates ### Cargo.toml Changes @@ -60,18 +53,6 @@ http = "0.2" hyper = { version = "0.14.26", features = ["server"] } tokio = "1.26.0" tower = "0.4" - -# Server SDK with legacy HTTP support -pokemon-service-server-sdk = { - path = "../pokemon-service-server-sdk/", - package = "pokemon-service-server-sdk-http0x", - features = ["request-id"] -} - -[dev-dependencies] -hyper = { version = "0.14.26", features = ["server", "client"] } -hyper-rustls = { version = "0.24", features = ["http2"] } -aws-smithy-legacy-http = { path = "../../../rust-runtime/aws-smithy-legacy-http/" } ``` **After (http@1.x/hyper@1.x):** @@ -82,20 +63,6 @@ hyper = { version = "1", features = ["server"] } hyper-util = { version = "0.1", features = ["tokio", "server", "server-auto", "service"] } tokio = { version = "1.26.0", features = ["rt-multi-thread", "macros"] } tower = "0.4" - -# Server SDK with http@1.x support -pokemon-service-server-sdk = { - path = "../pokemon-service-server-sdk/", - features = ["request-id"] -} - -[dev-dependencies] -bytes = "1" -http-body-util = "0.1" -hyper = { version = "1", features = ["server", "client"] } -hyper-util = { version = "0.1", features = ["client", "client-legacy", "http1", "http2"] } -hyper-rustls = { version = "0.27", features = ["http2"] } -aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime" } ``` **Key Changes:** @@ -104,48 +71,10 @@ aws-smithy-runtime = { path = "../../rust-runtime/aws-smithy-runtime" } - **New**: `hyper-util` crate for server and client utilities - **New**: `bytes` and `http-body-util` for body handling - `hyper-rustls`: `0.24` → `0.27` -- Server SDK package name: no longer needs `-http0x` suffix -- Replace `aws-smithy-legacy-http` with `aws-smithy-runtime` - -#### Client Dependencies - -**Before:** -```toml -[dependencies] -aws-smithy-runtime = { version = "1.0", features = ["client"] } -aws-smithy-runtime-api = "1.0" -``` - -**After:** -```toml -[dependencies] -aws-smithy-http-client = "1.0" # Replaces direct hyper usage -aws-smithy-runtime = { version = "1.0", features = ["client"] } -aws-smithy-runtime-api = "1.0" -``` ## Server-Side Changes -### 1. Import Changes - -**Before:** -```rust -use hyper::StatusCode; -``` - -**After:** -```rust -use http::StatusCode; -use pokemon_service_server_sdk::server::serve; -use tokio::net::TcpListener; -``` - -**Key Points:** -- `StatusCode` and other HTTP types now come from the `http` crate, not `hyper` -- Import the `serve` helper from your server SDK -- Use `tokio::net::TcpListener` instead of hyper's built-in listener - -### 2. Server Initialization +### 1. Server Initialization **Before (hyper@0.14):** ```rust @@ -196,10 +125,9 @@ pub async fn main() { **Key Changes:** 1. Replace `hyper::Server::bind(&bind)` with `TcpListener::bind(bind).await` 2. Use the `serve()` helper function instead of `.serve(make_app)` -3. TcpListener binding is now async (requires `.await`) -4. Can get actual bound address with `.local_addr()` (useful for testing with port 0) +3. Can get actual bound address with `.local_addr()` (useful for testing with port 0) -### 3. Service Building +### 2. Service Building The service building API remains the same: @@ -283,7 +211,6 @@ fn create_client() -> PokemonClient { 2. Use `tls::TlsContext` and `tls::TrustStore` instead of direct rustls config 3. Specify TLS provider explicitly (Rustls with AWS-LC or Ring crypto) 4. Use `.build_https()` instead of passing a connector -5. Much simpler API with better defaults ### Using Default Client @@ -298,152 +225,9 @@ let config = pokemon_service_client::Config::builder() let client = pokemon_service_client::Client::from_conf(config); ``` -## Test Infrastructure Updates - -### Test Helpers - -**Before (http@0.14):** -```rust -use std::{process::Command, time::Duration}; -use tokio::time::sleep; - -pub async fn run_server() -> ChildDrop { - let crate_name = std::env::var("CARGO_PKG_NAME").unwrap(); - let child = Command::cargo_bin(crate_name).unwrap().spawn().unwrap(); - sleep(Duration::from_millis(500)).await; - ChildDrop(child) -} - -pub fn base_url() -> String { - format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}") -} - -pub fn client() -> Client { - let config = Config::builder() - .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{DEFAULT_PORT}")) - .build(); - Client::from_conf(config) -} -``` - -**After (http@1.x with dynamic port detection):** -```rust -use std::{ - io::{BufRead, BufReader}, - process::{Command, Stdio}, - time::Duration, -}; -use tokio::time::timeout; - -pub struct ServerHandle { - pub child: ChildDrop, - pub port: u16, -} - -pub async fn run_server() -> ServerHandle { - let mut child = Command::new(assert_cmd::cargo::cargo_bin!("pokemon-service")) - .args(["--port", "0"]) // Use port 0 for random available port - .stderr(Stdio::piped()) - .spawn() - .unwrap(); - - // Wait for the server to signal it's ready by reading stderr - let stderr = child.stderr.take().unwrap(); - let ready_signal = tokio::task::spawn_blocking(move || { - let reader = BufReader::new(stderr); - for line in reader.lines() { - if let Ok(line) = line { - if let Some(port_str) = line.strip_prefix("SERVER_READY:") { - if let Ok(port) = port_str.parse::() { - return Some(port); - } - } - } - } - None - }); - - // Wait for the ready signal with a timeout - let port = match timeout(Duration::from_secs(5), ready_signal).await { - Ok(Ok(Some(port))) => port, - _ => panic!("Server did not become ready within 5 seconds"), - }; - - ServerHandle { - child: ChildDrop(child), - port, - } -} - -pub fn base_url(port: u16) -> String { - format!("http://{DEFAULT_ADDRESS}:{port}") -} - -pub fn client(port: u16) -> Client { - let config = Config::builder() - .endpoint_url(format!("http://{DEFAULT_ADDRESS}:{port}")) - .build(); - Client::from_conf(config) -} -``` - -**Key Improvements:** -1. **Dynamic port allocation**: Use port 0 to get a random available port -2. **Server ready signaling**: Wait for server to emit "SERVER_READY:{port}" before running tests -3. **No more sleep()**: Deterministic server startup detection -4. **Better test isolation**: Each test can run on its own port -5. **Timeout protection**: Fail fast if server doesn't start - -**Update your server to emit the ready signal:** -```rust -let listener = TcpListener::bind(bind).await.expect("failed to bind TCP listener"); -let actual_addr = listener.local_addr().expect("failed to get local address"); -eprintln!("SERVER_READY:{}", actual_addr.port()); -``` - -### Test Usage - -**Before:** -```rust -#[tokio::test] -async fn test_get_pokemon_species() { - let _child = common::run_server().await; - let client = common::client(); - // ... test code ... -} -``` - -**After:** -```rust -#[tokio::test] -async fn test_get_pokemon_species() { - let server = common::run_server().await; - let client = common::client(server.port); - // ... test code ... -} -``` - ## Common Migration Patterns -### 1. StatusCode Usage - -**Before:** -```rust -use hyper::StatusCode; - -let status = StatusCode::OK; -let status = StatusCode::NOT_FOUND; -``` - -**After:** -```rust -use http::StatusCode; - -let status = StatusCode::OK; -let status = StatusCode::NOT_FOUND; -``` - -### 2. Response Building +### 1. Response Building **Before:** ```rust @@ -457,7 +241,7 @@ let response = Response::builder() **After:** ```rust -use http::{Response, StatusCode}; +use aws_smithy_http_server::http::{Response, StatusCode}; use http_body_util::Full; use bytes::Bytes; @@ -467,20 +251,7 @@ let response = Response::builder() .unwrap(); ``` -### 3. Request Handling - -Most request handling code remains the same thanks to smithy-rs abstractions: - -```rust -// This works the same in both versions -pub async fn get_pokemon_species( - input: GetPokemonSpeciesInput, -) -> Result { - // Your handler code -} -``` - -### 4. Middleware and Layers +### 2. Middleware and Layers Tower layers continue to work the same way: @@ -560,14 +331,6 @@ http-body-util = "0.1" Then use the appropriate body types from `http-body-util`. -#### 5. Tests failing with "connection refused" - -**Problem:** -Tests start before server is ready. - -**Solution:** -Implement the server ready signaling pattern shown in [Test Infrastructure Updates](#test-infrastructure-updates). - ### Getting Help - **Examples**: Check the `examples/` directory for working http@1.x code @@ -575,71 +338,3 @@ Implement the server ready signaling pattern shown in [Test Infrastructure Updat - **Documentation**: https://docs.rs/aws-smithy-http-server/ - **GitHub Issues**: https://github.com/smithy-lang/smithy-rs/issues -## Migration Checklist - -Use this checklist to track your migration progress: - -### Pre-Migration -- [ ] Review this guide completely -- [ ] Backup your current working code -- [ ] Review the legacy examples in `examples/legacy/` -- [ ] Identify all places using http/hyper directly -- [ ] Plan for testing time - -### Dependencies -- [ ] Update `http` from `0.2` to `1` -- [ ] Update `hyper` from `0.14` to `1` -- [ ] Add `hyper-util` with required features -- [ ] Add `bytes` and `http-body-util` if needed -- [ ] Update `hyper-rustls` if used (0.24 → 0.27) -- [ ] Update server SDK package (remove `-http0x` suffix) -- [ ] Remove `aws-smithy-legacy-http` references -- [ ] Add `aws-smithy-runtime` if needed - -### Server Code -- [ ] Change `use hyper::StatusCode` to `use http::StatusCode` -- [ ] Import `serve` from server SDK -- [ ] Import `tokio::net::TcpListener` -- [ ] Replace `hyper::Server::bind()` with `TcpListener::bind().await` -- [ ] Replace `.serve(make_app)` with `serve(listener, make_app).await` -- [ ] Add server ready signaling (optional but recommended) - -### Client Code -- [ ] Replace `HyperClientBuilder` with `aws_smithy_http_client::Builder` -- [ ] Update TLS configuration to use new API -- [ ] Test custom connector setups - -### Test Code -- [ ] Update test helpers for dynamic port allocation -- [ ] Implement server ready detection -- [ ] Update all test usages to pass port parameter -- [ ] Remove arbitrary sleep() calls - -### Validation -- [ ] Run `cargo check` - fix compilation errors -- [ ] Run `cargo test` - ensure all tests pass -- [ ] Run `cargo clippy` - address warnings -- [ ] Manual testing of all endpoints -- [ ] Load/performance testing if applicable -- [ ] Review security configurations (TLS, auth) - -### Documentation -- [ ] Update README with new dependency versions -- [ ] Update code examples in documentation -- [ ] Add migration notes for your team -- [ ] Update deployment scripts if needed - -### Deployment -- [ ] Test in development environment -- [ ] Test in staging environment -- [ ] Plan rollback strategy -- [ ] Deploy to production -- [ ] Monitor for issues - -## Conclusion - -Migrating from http@0.2/hyper@0.14 to http@1.x/hyper@1.x involves updating dependencies and making targeted changes to server initialization and client setup code. The smithy-rs abstractions shield you from many breaking changes, making the migration more straightforward than a raw hyper upgrade. - -The new versions offer improved performance, better APIs, and are the future of the Rust HTTP ecosystem. While migration requires effort, the benefits make it worthwhile. - -For additional help, consult the working examples in the `examples/` directory or reach out through GitHub issues.