AWS SDK

AWS SDK

rev. eb19c4c7998eaae1210cb747286b497c3425236c (ignoring whitespace)

Files changed:

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/config/endpoint/internals.rs

@@ -0,1 +0,123 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
#[allow(
           3  +
    clippy::collapsible_if,
           4  +
    clippy::bool_comparison,
           5  +
    clippy::nonminimal_bool,
           6  +
    clippy::comparison_to_empty,
           7  +
    clippy::redundant_pattern_matching,
           8  +
    clippy::useless_asref
           9  +
)]
          10  +
pub(super) fn resolve_endpoint(
          11  +
    _params: &crate::config::endpoint::Params,
          12  +
    _diagnostic_collector: &mut crate::endpoint_lib::diagnostic::DiagnosticCollector,
          13  +
    partition_resolver: &crate::endpoint_lib::partition::PartitionResolver,
          14  +
) -> ::aws_smithy_http::endpoint::Result {
          15  +
    #[allow(unused_variables)]
          16  +
    let region = &_params.region;
          17  +
    #[allow(unused_variables)]
          18  +
    let use_dual_stack = &_params.use_dual_stack;
          19  +
    #[allow(unused_variables)]
          20  +
    let use_fips = &_params.use_fips;
          21  +
    #[allow(unused_variables)]
          22  +
    let endpoint = &_params.endpoint;
          23  +
    #[allow(unused_variables)]
          24  +
    if let Some(endpoint) = endpoint {
          25  +
        if (*use_fips) == (true) {
          26  +
            return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
          27  +
                "Invalid Configuration: FIPS and custom endpoint are not supported".to_string(),
          28  +
            ));
          29  +
        }
          30  +
        if (*use_dual_stack) == (true) {
          31  +
            return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
          32  +
                "Invalid Configuration: Dualstack and custom endpoint are not supported".to_string(),
          33  +
            ));
          34  +
        }
          35  +
        return Ok(::aws_smithy_types::endpoint::Endpoint::builder().url(endpoint.to_owned()).build());
          36  +
    }
          37  +
    #[allow(unused_variables)]
          38  +
    if let Some(region) = region {
          39  +
        #[allow(unused_variables)]
          40  +
        if let Some(partition_result) = partition_resolver.resolve_partition(region.as_ref() as &str, _diagnostic_collector) {
          41  +
            if (*use_fips) == (true) {
          42  +
                if (*use_dual_stack) == (true) {
          43  +
                    if (true) == (partition_result.supports_fips()) {
          44  +
                        if (true) == (partition_result.supports_dual_stack()) {
          45  +
                            return Ok(::aws_smithy_types::endpoint::Endpoint::builder()
          46  +
                                .url({
          47  +
                                    let mut out = String::new();
          48  +
                                    out.push_str("https://session.qldb-fips.");
          49  +
                                    #[allow(clippy::needless_borrow)]
          50  +
                                    out.push_str(&region.as_ref() as &str);
          51  +
                                    out.push('.');
          52  +
                                    #[allow(clippy::needless_borrow)]
          53  +
                                    out.push_str(&partition_result.dual_stack_dns_suffix());
          54  +
                                    out
          55  +
                                })
          56  +
                                .build());
          57  +
                        }
          58  +
                    }
          59  +
                    return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
          60  +
                        "FIPS and DualStack are enabled, but this partition does not support one or both".to_string(),
          61  +
                    ));
          62  +
                }
          63  +
            }
          64  +
            if (*use_fips) == (true) {
          65  +
                if (partition_result.supports_fips()) == (true) {
          66  +
                    return Ok(::aws_smithy_types::endpoint::Endpoint::builder()
          67  +
                        .url({
          68  +
                            let mut out = String::new();
          69  +
                            out.push_str("https://session.qldb-fips.");
          70  +
                            #[allow(clippy::needless_borrow)]
          71  +
                            out.push_str(&region.as_ref() as &str);
          72  +
                            out.push('.');
          73  +
                            #[allow(clippy::needless_borrow)]
          74  +
                            out.push_str(&partition_result.dns_suffix());
          75  +
                            out
          76  +
                        })
          77  +
                        .build());
          78  +
                }
          79  +
                return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
          80  +
                    "FIPS is enabled but this partition does not support FIPS".to_string(),
          81  +
                ));
          82  +
            }
          83  +
            if (*use_dual_stack) == (true) {
          84  +
                if (true) == (partition_result.supports_dual_stack()) {
          85  +
                    return Ok(::aws_smithy_types::endpoint::Endpoint::builder()
          86  +
                        .url({
          87  +
                            let mut out = String::new();
          88  +
                            out.push_str("https://session.qldb.");
          89  +
                            #[allow(clippy::needless_borrow)]
          90  +
                            out.push_str(&region.as_ref() as &str);
          91  +
                            out.push('.');
          92  +
                            #[allow(clippy::needless_borrow)]
          93  +
                            out.push_str(&partition_result.dual_stack_dns_suffix());
          94  +
                            out
          95  +
                        })
          96  +
                        .build());
          97  +
                }
          98  +
                return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
          99  +
                    "DualStack is enabled but this partition does not support DualStack".to_string(),
         100  +
                ));
         101  +
            }
         102  +
            return Ok(::aws_smithy_types::endpoint::Endpoint::builder()
         103  +
                .url({
         104  +
                    let mut out = String::new();
         105  +
                    out.push_str("https://session.qldb.");
         106  +
                    #[allow(clippy::needless_borrow)]
         107  +
                    out.push_str(&region.as_ref() as &str);
         108  +
                    out.push('.');
         109  +
                    #[allow(clippy::needless_borrow)]
         110  +
                    out.push_str(&partition_result.dns_suffix());
         111  +
                    out
         112  +
                })
         113  +
                .build());
         114  +
        }
         115  +
        #[allow(unreachable_code)]
         116  +
        return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(format!(
         117  +
            "No rules matched these parameters. This is a bug. {_params:?}"
         118  +
        )));
         119  +
    }
         120  +
    return Err(::aws_smithy_http::endpoint::ResolveEndpointError::message(
         121  +
        "Invalid Configuration: Missing Region".to_string(),
         122  +
    ));
         123  +
}

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/config/http.rs

@@ -0,1 +0,3 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
pub use ::aws_smithy_runtime_api::client::orchestrator::HttpRequest;
           3  +
pub use ::aws_smithy_runtime_api::client::orchestrator::HttpResponse;

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/config/interceptors.rs

@@ -0,1 +0,11 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::AfterDeserializationInterceptorContextRef;
           3  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeDeserializationInterceptorContextMut;
           4  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeDeserializationInterceptorContextRef;
           5  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeSerializationInterceptorContextMut;
           6  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeSerializationInterceptorContextRef;
           7  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextMut;
           8  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::BeforeTransmitInterceptorContextRef;
           9  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::FinalizerInterceptorContextMut;
          10  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::FinalizerInterceptorContextRef;
          11  +
pub use ::aws_smithy_runtime_api::client::interceptors::context::InterceptorContext;

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/config/retry.rs

@@ -0,1 +0,7 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
pub use ::aws_smithy_runtime_api::client::retries::classifiers::ClassifyRetry;
           3  +
pub use ::aws_smithy_runtime_api::client::retries::classifiers::RetryAction;
           4  +
pub use ::aws_smithy_runtime_api::client::retries::ShouldAttempt;
           5  +
           6  +
pub use ::aws_smithy_runtime::client::retries::{ClientRateLimiter, RetryPartition, TokenBucket};
           7  +
pub use ::aws_smithy_types::retry::{ReconnectMode, RetryConfig, RetryConfigBuilder, RetryMode};

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/config/timeout.rs

@@ -0,1 +0,2 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
pub use ::aws_smithy_types::timeout::{TimeoutConfig, TimeoutConfigBuilder};

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/endpoint_lib.rs

@@ -0,1 +0,20 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
// Loading the partition JSON is expensive since it involves many regex compilations,
           3  +
// so cache the result so that it only need to be paid for the first constructed client.
           4  +
pub(crate) static DEFAULT_PARTITION_RESOLVER: std::sync::LazyLock<crate::endpoint_lib::partition::PartitionResolver> = std::sync::LazyLock::new(
           5  +
    || match std::env::var("SMITHY_CLIENT_SDK_CUSTOM_PARTITION") {
           6  +
        Ok(partitions) => {
           7  +
            ::tracing::debug!("loading custom partitions located at {partitions}");
           8  +
            let partition_dot_json = std::fs::read_to_string(partitions).expect("should be able to read a custom partition JSON");
           9  +
            crate::endpoint_lib::partition::PartitionResolver::new_from_json(partition_dot_json.as_bytes()).expect("valid JSON")
          10  +
        }
          11  +
        _ => {
          12  +
            ::tracing::debug!("loading default partitions");
          13  +
            crate::endpoint_lib::partition::PartitionResolver::new_from_json(b"{\"partitions\":[{\"id\":\"aws\",\"outputs\":{\"dnsSuffix\":\"amazonaws.com\",\"dualStackDnsSuffix\":\"api.aws\",\"implicitGlobalRegion\":\"us-east-1\",\"name\":\"aws\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^(us|eu|ap|sa|ca|me|af|il|mx)\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"af-south-1\":{\"description\":\"Africa (Cape Town)\"},\"ap-east-1\":{\"description\":\"Asia Pacific (Hong Kong)\"},\"ap-east-2\":{\"description\":\"Asia Pacific (Taipei)\"},\"ap-northeast-1\":{\"description\":\"Asia Pacific (Tokyo)\"},\"ap-northeast-2\":{\"description\":\"Asia Pacific (Seoul)\"},\"ap-northeast-3\":{\"description\":\"Asia Pacific (Osaka)\"},\"ap-south-1\":{\"description\":\"Asia Pacific (Mumbai)\"},\"ap-south-2\":{\"description\":\"Asia Pacific (Hyderabad)\"},\"ap-southeast-1\":{\"description\":\"Asia Pacific (Singapore)\"},\"ap-southeast-2\":{\"description\":\"Asia Pacific (Sydney)\"},\"ap-southeast-3\":{\"description\":\"Asia Pacific (Jakarta)\"},\"ap-southeast-4\":{\"description\":\"Asia Pacific (Melbourne)\"},\"ap-southeast-5\":{\"description\":\"Asia Pacific (Malaysia)\"},\"ap-southeast-6\":{\"description\":\"Asia Pacific (New Zealand)\"},\"ap-southeast-7\":{\"description\":\"Asia Pacific (Thailand)\"},\"aws-global\":{\"description\":\"aws global region\"},\"ca-central-1\":{\"description\":\"Canada (Central)\"},\"ca-west-1\":{\"description\":\"Canada West (Calgary)\"},\"eu-central-1\":{\"description\":\"Europe (Frankfurt)\"},\"eu-central-2\":{\"description\":\"Europe (Zurich)\"},\"eu-north-1\":{\"description\":\"Europe (Stockholm)\"},\"eu-south-1\":{\"description\":\"Europe (Milan)\"},\"eu-south-2\":{\"description\":\"Europe (Spain)\"},\"eu-west-1\":{\"description\":\"Europe (Ireland)\"},\"eu-west-2\":{\"description\":\"Europe (London)\"},\"eu-west-3\":{\"description\":\"Europe (Paris)\"},\"il-central-1\":{\"description\":\"Israel (Tel Aviv)\"},\"me-central-1\":{\"description\":\"Middle East (UAE)\"},\"me-south-1\":{\"description\":\"Middle East (Bahrain)\"},\"mx-central-1\":{\"description\":\"Mexico (Central)\"},\"sa-east-1\":{\"description\":\"South America (Sao Paulo)\"},\"us-east-1\":{\"description\":\"US East (N. Virginia)\"},\"us-east-2\":{\"description\":\"US East (Ohio)\"},\"us-west-1\":{\"description\":\"US West (N. California)\"},\"us-west-2\":{\"description\":\"US West (Oregon)\"}}},{\"id\":\"aws-cn\",\"outputs\":{\"dnsSuffix\":\"amazonaws.com.cn\",\"dualStackDnsSuffix\":\"api.amazonwebservices.com.cn\",\"implicitGlobalRegion\":\"cn-northwest-1\",\"name\":\"aws-cn\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^cn\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-cn-global\":{\"description\":\"aws-cn global region\"},\"cn-north-1\":{\"description\":\"China (Beijing)\"},\"cn-northwest-1\":{\"description\":\"China (Ningxia)\"}}},{\"id\":\"aws-eusc\",\"outputs\":{\"dnsSuffix\":\"amazonaws.eu\",\"dualStackDnsSuffix\":\"api.amazonwebservices.eu\",\"implicitGlobalRegion\":\"eusc-de-east-1\",\"name\":\"aws-eusc\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^eusc\\\\-(de)\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"eusc-de-east-1\":{\"description\":\"EU (Germany)\"}}},{\"id\":\"aws-iso\",\"outputs\":{\"dnsSuffix\":\"c2s.ic.gov\",\"dualStackDnsSuffix\":\"api.aws.ic.gov\",\"implicitGlobalRegion\":\"us-iso-east-1\",\"name\":\"aws-iso\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^us\\\\-iso\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-iso-global\":{\"description\":\"aws-iso global region\"},\"us-iso-east-1\":{\"description\":\"US ISO East\"},\"us-iso-west-1\":{\"description\":\"US ISO WEST\"}}},{\"id\":\"aws-iso-b\",\"outputs\":{\"dnsSuffix\":\"sc2s.sgov.gov\",\"dualStackDnsSuffix\":\"api.aws.scloud\",\"implicitGlobalRegion\":\"us-isob-east-1\",\"name\":\"aws-iso-b\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^us\\\\-isob\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-iso-b-global\":{\"description\":\"aws-iso-b global region\"},\"us-isob-east-1\":{\"description\":\"US ISOB East (Ohio)\"}}},{\"id\":\"aws-iso-e\",\"outputs\":{\"dnsSuffix\":\"cloud.adc-e.uk\",\"dualStackDnsSuffix\":\"api.cloud-aws.adc-e.uk\",\"implicitGlobalRegion\":\"eu-isoe-west-1\",\"name\":\"aws-iso-e\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^eu\\\\-isoe\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-iso-e-global\":{\"description\":\"aws-iso-e global region\"},\"eu-isoe-west-1\":{\"description\":\"EU ISOE West\"}}},{\"id\":\"aws-iso-f\",\"outputs\":{\"dnsSuffix\":\"csp.hci.ic.gov\",\"dualStackDnsSuffix\":\"api.aws.hci.ic.gov\",\"implicitGlobalRegion\":\"us-isof-south-1\",\"name\":\"aws-iso-f\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^us\\\\-isof\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-iso-f-global\":{\"description\":\"aws-iso-f global region\"},\"us-isof-east-1\":{\"description\":\"US ISOF EAST\"},\"us-isof-south-1\":{\"description\":\"US ISOF SOUTH\"}}},{\"id\":\"aws-us-gov\",\"outputs\":{\"dnsSuffix\":\"amazonaws.com\",\"dualStackDnsSuffix\":\"api.aws\",\"implicitGlobalRegion\":\"us-gov-west-1\",\"name\":\"aws-us-gov\",\"supportsDualStack\":true,\"supportsFIPS\":true},\"regionRegex\":\"^us\\\\-gov\\\\-\\\\w+\\\\-\\\\d+$\",\"regions\":{\"aws-us-gov-global\":{\"description\":\"aws-us-gov global region\"},\"us-gov-east-1\":{\"description\":\"AWS GovCloud (US-East)\"},\"us-gov-west-1\":{\"description\":\"AWS GovCloud (US-West)\"}}}],\"version\":\"1.1\"}").expect("valid JSON")
          14  +
        }
          15  +
    },
          16  +
);
          17  +
          18  +
pub(crate) mod diagnostic;
          19  +
          20  +
pub(crate) mod partition;

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/endpoint_lib/diagnostic.rs

@@ -0,1 +0,45 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
/*
           3  +
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           4  +
 *  SPDX-License-Identifier: Apache-2.0
           5  +
 */
           6  +
           7  +
use std::error::Error;
           8  +
           9  +
/// Diagnostic collector for endpoint resolution
          10  +
///
          11  +
/// Endpoint functions return `Option<T>`—to enable diagnostic information to flow, we capture the
          12  +
/// last error that occurred.
          13  +
#[derive(Debug, Default)]
          14  +
pub(crate) struct DiagnosticCollector {
          15  +
    last_error: Option<Box<dyn Error + Send + Sync>>,
          16  +
}
          17  +
          18  +
impl DiagnosticCollector {
          19  +
    #[allow(unused)]
          20  +
    /// Report an error to the collector
          21  +
    pub(crate) fn report_error(&mut self, err: impl Into<Box<dyn Error + Send + Sync>>) {
          22  +
        self.last_error = Some(err.into());
          23  +
    }
          24  +
          25  +
    #[allow(unused)]
          26  +
    /// Capture a result, returning Some(t) when the input was `Ok` and `None` otherwise
          27  +
    pub(crate) fn capture<T, E: Into<Box<dyn Error + Send + Sync>>>(&mut self, err: Result<T, E>) -> Option<T> {
          28  +
        match err {
          29  +
            Ok(res) => Some(res),
          30  +
            Err(e) => {
          31  +
                self.report_error(e);
          32  +
                None
          33  +
            }
          34  +
        }
          35  +
    }
          36  +
          37  +
    pub(crate) fn take_last_error(&mut self) -> Option<Box<dyn Error + Send + Sync>> {
          38  +
        self.last_error.take()
          39  +
    }
          40  +
          41  +
    /// Create a new diagnostic collector
          42  +
    pub(crate) fn new() -> Self {
          43  +
        Self { last_error: None }
          44  +
    }
          45  +
}

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/endpoint_lib/partition.rs

@@ -0,1 +0,557 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
/*
           3  +
 *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           4  +
 *  SPDX-License-Identifier: Apache-2.0
           5  +
 */
           6  +
           7  +
//! Partition function to determine a partition for a given region
           8  +
//!
           9  +
//! This function supports adding regions dynamically, parsing a JSON file, and builder construction.
          10  +
//!
          11  +
//! If, at a future point, this interface stabilizes it is a good candidate for extraction into a
          12  +
//! shared crate.
          13  +
use crate::endpoint_lib::diagnostic::DiagnosticCollector;
          14  +
use crate::endpoint_lib::partition::deser::deserialize_partitions;
          15  +
use aws_smithy_json::deserialize::error::DeserializeError;
          16  +
use regex_lite::Regex;
          17  +
use std::borrow::Cow;
          18  +
use std::collections::HashMap;
          19  +
          20  +
/// Determine the AWS partition metadata for a given region
          21  +
#[derive(Clone, Debug, Default)]
          22  +
pub(crate) struct PartitionResolver {
          23  +
    partitions: Vec<PartitionMetadata>,
          24  +
}
          25  +
          26  +
impl PartitionResolver {
          27  +
    pub(crate) fn from_partitions(partitions: Vec<PartitionMetadata>) -> Self {
          28  +
        Self { partitions }
          29  +
    }
          30  +
}
          31  +
          32  +
/// Partition result returned from partition resolver
          33  +
pub(crate) struct Partition<'a> {
          34  +
    name: &'a str,
          35  +
    dns_suffix: &'a str,
          36  +
    dual_stack_dns_suffix: &'a str,
          37  +
    supports_fips: bool,
          38  +
    supports_dual_stack: bool,
          39  +
    implicit_global_region: &'a str,
          40  +
}
          41  +
          42  +
#[allow(unused)]
          43  +
impl Partition<'_> {
          44  +
    pub(crate) fn name(&self) -> &str {
          45  +
        self.name
          46  +
    }
          47  +
          48  +
    pub(crate) fn dns_suffix(&self) -> &str {
          49  +
        self.dns_suffix
          50  +
    }
          51  +
          52  +
    pub(crate) fn supports_fips(&self) -> bool {
          53  +
        self.supports_fips
          54  +
    }
          55  +
          56  +
    pub(crate) fn dual_stack_dns_suffix(&self) -> &str {
          57  +
        self.dual_stack_dns_suffix
          58  +
    }
          59  +
          60  +
    pub(crate) fn supports_dual_stack(&self) -> bool {
          61  +
        self.supports_dual_stack
          62  +
    }
          63  +
          64  +
    pub(crate) fn implicit_global_region(&self) -> &str {
          65  +
        self.implicit_global_region
          66  +
    }
          67  +
}
          68  +
          69  +
static DEFAULT_OVERRIDE: &PartitionOutputOverride = &PartitionOutputOverride {
          70  +
    name: None,
          71  +
    dns_suffix: None,
          72  +
    dual_stack_dns_suffix: None,
          73  +
    supports_fips: None,
          74  +
    supports_dual_stack: None,
          75  +
    implicit_global_region: None,
          76  +
};
          77  +
          78  +
/// Merge the base output and the override output, dealing with `Cow`s
          79  +
macro_rules! merge {
          80  +
    ($base: expr, $output: expr, $field: ident) => {
          81  +
        $output.$field.as_ref().map(|s| s.as_ref()).unwrap_or($base.outputs.$field.as_ref())
          82  +
    };
          83  +
}
          84  +
          85  +
impl PartitionResolver {
          86  +
    #[allow(unused)]
          87  +
    pub(crate) fn empty() -> PartitionResolver {
          88  +
        PartitionResolver { partitions: vec![] }
          89  +
    }
          90  +
          91  +
    #[allow(unused)]
          92  +
    pub(crate) fn add_partition(&mut self, partition: PartitionMetadata) {
          93  +
        self.partitions.push(partition);
          94  +
    }
          95  +
          96  +
    pub(crate) fn new_from_json(partition_dot_json: &[u8]) -> Result<PartitionResolver, DeserializeError> {
          97  +
        deserialize_partitions(partition_dot_json)
          98  +
    }
          99  +
         100  +
    /// Resolve a partition for a given region
         101  +
    ///
         102  +
    /// 1. Enumerate each partition in the `partitions` array, and determine if the identifier to be
         103  +
    ///    resolved matches an explicit region listed in the `regions` array for a given partition.
         104  +
    ///    If identifier matches, proceed to step 4, otherwise continue to step 2.
         105  +
    /// 2. Enumerate each partition in the `partitions` array, use the regular expression
         106  +
    ///    `regionRegex` to determine if the identifier matches the regular expression. If the
         107  +
    ///    identifier matches, proceed to step 4, otherwise continue to step 3.
         108  +
    /// 3. If no partition is matched after exhausting step 1 and step 2, then fallback to matching
         109  +
    ///    the identifier to the partition where `id == "aws"`, and proceed to step 4. If no `aws`
         110  +
    ///    partition is present, return `None`.
         111  +
    /// 4. After matching the identifier to a partition using one of the previous steps, the partition function should return a
         112  +
    ///    typed data structure containing the fields in `outputs` in the matched partition. **Important:** If a specific region
         113  +
    ///    was matched, the properties associated with that region **MUST** be merged with the `outputs` field.
         114  +
    pub(crate) fn resolve_partition(&self, region: &str, e: &mut DiagnosticCollector) -> Option<Partition<'_>> {
         115  +
        let mut explicit_match_partition = self.partitions.iter().flat_map(|part| part.explicit_match(region));
         116  +
        let mut regex_match_partition = self.partitions.iter().flat_map(|part| part.regex_match(region));
         117  +
         118  +
        let (base, region_override) = explicit_match_partition.next().or_else(|| regex_match_partition.next()).or_else(|| {
         119  +
            match self.partitions.iter().find(|p| p.id == "aws") {
         120  +
                Some(partition) => Some((partition, None)),
         121  +
                None => {
         122  +
                    e.report_error("no AWS partition!");
         123  +
                    None
         124  +
                }
         125  +
            }
         126  +
        })?;
         127  +
        let region_override = region_override.as_ref().unwrap_or(&DEFAULT_OVERRIDE);
         128  +
        Some(Partition {
         129  +
            name: merge!(base, region_override, name),
         130  +
            dns_suffix: merge!(base, region_override, dns_suffix),
         131  +
            dual_stack_dns_suffix: merge!(base, region_override, dual_stack_dns_suffix),
         132  +
            supports_fips: region_override.supports_fips.unwrap_or(base.outputs.supports_fips),
         133  +
            supports_dual_stack: region_override.supports_dual_stack.unwrap_or(base.outputs.supports_dual_stack),
         134  +
            implicit_global_region: merge!(base, region_override, implicit_global_region),
         135  +
        })
         136  +
    }
         137  +
}
         138  +
         139  +
type Str = Cow<'static, str>;
         140  +
         141  +
#[derive(Clone, Debug)]
         142  +
pub(crate) struct PartitionMetadata {
         143  +
    id: Str,
         144  +
    region_regex: Regex,
         145  +
    regions: HashMap<Str, PartitionOutputOverride>,
         146  +
    outputs: PartitionOutput,
         147  +
}
         148  +
         149  +
#[derive(Default)]
         150  +
pub(crate) struct PartitionMetadataBuilder {
         151  +
    pub(crate) id: Option<Str>,
         152  +
    pub(crate) region_regex: Option<Regex>,
         153  +
    pub(crate) regions: HashMap<Str, PartitionOutputOverride>,
         154  +
    pub(crate) outputs: Option<PartitionOutputOverride>,
         155  +
}
         156  +
         157  +
impl PartitionMetadataBuilder {
         158  +
    pub(crate) fn build(self) -> PartitionMetadata {
         159  +
        PartitionMetadata {
         160  +
            id: self.id.expect("id must be defined"),
         161  +
            region_regex: self.region_regex.expect("region regex must be defined"),
         162  +
            regions: self.regions,
         163  +
            outputs: self
         164  +
                .outputs
         165  +
                .expect("outputs must be defined")
         166  +
                .into_partition_output()
         167  +
                .expect("missing fields on outputs"),
         168  +
        }
         169  +
    }
         170  +
}
         171  +
         172  +
impl PartitionMetadata {
         173  +
    fn explicit_match(&self, region: &str) -> Option<(&PartitionMetadata, Option<&PartitionOutputOverride>)> {
         174  +
        self.regions.get(region).map(|output_override| (self, Some(output_override)))
         175  +
    }
         176  +
         177  +
    fn regex_match(&self, region: &str) -> Option<(&PartitionMetadata, Option<&PartitionOutputOverride>)> {
         178  +
        if self.region_regex.is_match(region) {
         179  +
            Some((self, None))
         180  +
        } else {
         181  +
            None
         182  +
        }
         183  +
    }
         184  +
}
         185  +
         186  +
#[derive(Clone, Debug)]
         187  +
pub(crate) struct PartitionOutput {
         188  +
    name: Str,
         189  +
    dns_suffix: Str,
         190  +
    dual_stack_dns_suffix: Str,
         191  +
    supports_fips: bool,
         192  +
    supports_dual_stack: bool,
         193  +
    implicit_global_region: Str,
         194  +
}
         195  +
         196  +
#[derive(Clone, Debug, Default)]
         197  +
pub(crate) struct PartitionOutputOverride {
         198  +
    name: Option<Str>,
         199  +
    dns_suffix: Option<Str>,
         200  +
    dual_stack_dns_suffix: Option<Str>,
         201  +
    supports_fips: Option<bool>,
         202  +
    supports_dual_stack: Option<bool>,
         203  +
    implicit_global_region: Option<Str>,
         204  +
}
         205  +
         206  +
impl PartitionOutputOverride {
         207  +
    pub(crate) fn into_partition_output(self) -> Result<PartitionOutput, Box<dyn std::error::Error>> {
         208  +
        Ok(PartitionOutput {
         209  +
            name: self.name.ok_or("missing name")?,
         210  +
            dns_suffix: self.dns_suffix.ok_or("missing dnsSuffix")?,
         211  +
            dual_stack_dns_suffix: self.dual_stack_dns_suffix.ok_or("missing dual_stackDnsSuffix")?,
         212  +
            supports_fips: self.supports_fips.ok_or("missing supports fips")?,
         213  +
            supports_dual_stack: self.supports_dual_stack.ok_or("missing supportsDualstack")?,
         214  +
            implicit_global_region: self.implicit_global_region.ok_or("missing implicitGlobalRegion")?,
         215  +
        })
         216  +
    }
         217  +
}
         218  +
         219  +
/// JSON deserializers for partition metadata
         220  +
///
         221  +
/// This code was generated by smithy-rs and then hand edited for clarity
         222  +
mod deser {
         223  +
    use crate::endpoint_lib::partition::{PartitionMetadata, PartitionMetadataBuilder, PartitionOutputOverride, PartitionResolver};
         224  +
    use aws_smithy_json::deserialize::token::{expect_bool_or_null, expect_start_object, expect_string_or_null, skip_value};
         225  +
    use aws_smithy_json::deserialize::{error::DeserializeError, json_token_iter, Token};
         226  +
    use regex_lite::Regex;
         227  +
    use std::borrow::Cow;
         228  +
    use std::collections::HashMap;
         229  +
         230  +
    pub(crate) fn deserialize_partitions(value: &[u8]) -> Result<PartitionResolver, DeserializeError> {
         231  +
        let mut tokens_owned = json_token_iter(value).peekable();
         232  +
        let tokens = &mut tokens_owned;
         233  +
        expect_start_object(tokens.next())?;
         234  +
        let mut resolver = None;
         235  +
        loop {
         236  +
            match tokens.next().transpose()? {
         237  +
                Some(Token::EndObject { .. }) => break,
         238  +
                Some(Token::ObjectKey { key, .. }) => match key.to_unescaped()?.as_ref() {
         239  +
                    "partitions" => {
         240  +
                        resolver = Some(PartitionResolver::from_partitions(deser_partitions(tokens)?));
         241  +
                    }
         242  +
                    _ => skip_value(tokens)?,
         243  +
                },
         244  +
                other => return Err(DeserializeError::custom(format!("expected object key or end object, found: {other:?}",))),
         245  +
            }
         246  +
        }
         247  +
        if tokens.next().is_some() {
         248  +
            return Err(DeserializeError::custom("found more JSON tokens after completing parsing"));
         249  +
        }
         250  +
        resolver.ok_or_else(|| DeserializeError::custom("did not find partitions array"))
         251  +
    }
         252  +
         253  +
    fn deser_partitions<'a, I>(tokens: &mut std::iter::Peekable<I>) -> Result<Vec<PartitionMetadata>, DeserializeError>
         254  +
    where
         255  +
        I: Iterator<Item = Result<Token<'a>, DeserializeError>>,
         256  +
    {
         257  +
        match tokens.next().transpose()? {
         258  +
            Some(Token::StartArray { .. }) => {
         259  +
                let mut items = Vec::new();
         260  +
                loop {
         261  +
                    match tokens.peek() {
         262  +
                        Some(Ok(Token::EndArray { .. })) => {
         263  +
                            tokens.next().transpose().unwrap();
         264  +
                            break;
         265  +
                        }
         266  +
                        _ => {
         267  +
                            items.push(deser_partition(tokens)?);
         268  +
                        }
         269  +
                    }
         270  +
                }
         271  +
                Ok(items)
         272  +
            }
         273  +
            _ => Err(DeserializeError::custom("expected start array")),
         274  +
        }
         275  +
    }
         276  +
         277  +
    pub(crate) fn deser_partition<'a, I>(tokens: &mut std::iter::Peekable<I>) -> Result<PartitionMetadata, DeserializeError>
         278  +
    where
         279  +
        I: Iterator<Item = Result<Token<'a>, DeserializeError>>,
         280  +
    {
         281  +
        match tokens.next().transpose()? {
         282  +
            Some(Token::StartObject { .. }) => {
         283  +
                let mut builder = PartitionMetadataBuilder::default();
         284  +
                loop {
         285  +
                    match tokens.next().transpose()? {
         286  +
                        Some(Token::EndObject { .. }) => break,
         287  +
                        Some(Token::ObjectKey { key, .. }) => match key.to_unescaped()?.as_ref() {
         288  +
                            "id" => {
         289  +
                                builder.id = token_to_str(tokens.next())?;
         290  +
                            }
         291  +
                            "regionRegex" => {
         292  +
                                builder.region_regex = token_to_str(tokens.next())?
         293  +
                                    .map(|region_regex| Regex::new(&region_regex))
         294  +
                                    .transpose()
         295  +
                                    .map_err(|_e| DeserializeError::custom("invalid regex"))?;
         296  +
                            }
         297  +
                            "regions" => {
         298  +
                                builder.regions = deser_explicit_regions(tokens)?;
         299  +
                            }
         300  +
                            "outputs" => {
         301  +
                                builder.outputs = deser_outputs(tokens)?;
         302  +
                            }
         303  +
                            _ => skip_value(tokens)?,
         304  +
                        },
         305  +
                        other => return Err(DeserializeError::custom(format!("expected object key or end object, found: {other:?}"))),
         306  +
                    }
         307  +
                }
         308  +
                Ok(builder.build())
         309  +
            }
         310  +
            _ => Err(DeserializeError::custom("expected start object")),
         311  +
        }
         312  +
    }
         313  +
         314  +
    #[allow(clippy::type_complexity, non_snake_case)]
         315  +
    pub(crate) fn deser_explicit_regions<'a, I>(
         316  +
        tokens: &mut std::iter::Peekable<I>,
         317  +
    ) -> Result<HashMap<super::Str, PartitionOutputOverride>, DeserializeError>
         318  +
    where
         319  +
        I: Iterator<Item = Result<Token<'a>, DeserializeError>>,
         320  +
    {
         321  +
        match tokens.next().transpose()? {
         322  +
            Some(Token::StartObject { .. }) => {
         323  +
                let mut map = HashMap::new();
         324  +
                loop {
         325  +
                    match tokens.next().transpose()? {
         326  +
                        Some(Token::EndObject { .. }) => break,
         327  +
                        Some(Token::ObjectKey { key, .. }) => {
         328  +
                            let key = key.to_unescaped().map(|u| u.into_owned())?;
         329  +
                            let value = deser_outputs(tokens)?;
         330  +
                            if let Some(value) = value {
         331  +
                                map.insert(key.into(), value);
         332  +
                            }
         333  +
                        }
         334  +
                        other => return Err(DeserializeError::custom(format!("expected object key or end object, found: {other:?}"))),
         335  +
                    }
         336  +
                }
         337  +
                Ok(map)
         338  +
            }
         339  +
            _ => Err(DeserializeError::custom("expected start object")),
         340  +
        }
         341  +
    }
         342  +
         343  +
    /// Convert a token to `Str` (a potentially static String)
         344  +
    fn token_to_str(token: Option<Result<Token, DeserializeError>>) -> Result<Option<super::Str>, DeserializeError> {
         345  +
        Ok(expect_string_or_null(token)?
         346  +
            .map(|s| s.to_unescaped().map(|u| u.into_owned()))
         347  +
            .transpose()?
         348  +
            .map(Cow::Owned))
         349  +
    }
         350  +
         351  +
    fn deser_outputs<'a, I>(tokens: &mut std::iter::Peekable<I>) -> Result<Option<PartitionOutputOverride>, DeserializeError>
         352  +
    where
         353  +
        I: Iterator<Item = Result<Token<'a>, DeserializeError>>,
         354  +
    {
         355  +
        match tokens.next().transpose()? {
         356  +
            Some(Token::StartObject { .. }) => {
         357  +
                #[allow(unused_mut)]
         358  +
                let mut builder = PartitionOutputOverride::default();
         359  +
                loop {
         360  +
                    match tokens.next().transpose()? {
         361  +
                        Some(Token::EndObject { .. }) => break,
         362  +
                        Some(Token::ObjectKey { key, .. }) => match key.to_unescaped()?.as_ref() {
         363  +
                            "name" => {
         364  +
                                builder.name = token_to_str(tokens.next())?;
         365  +
                            }
         366  +
                            "dnsSuffix" => {
         367  +
                                builder.dns_suffix = token_to_str(tokens.next())?;
         368  +
                            }
         369  +
                            "dualStackDnsSuffix" => {
         370  +
                                builder.dual_stack_dns_suffix = token_to_str(tokens.next())?;
         371  +
                            }
         372  +
                            "supportsFIPS" => {
         373  +
                                builder.supports_fips = expect_bool_or_null(tokens.next())?;
         374  +
                            }
         375  +
                            "supportsDualStack" => {
         376  +
                                builder.supports_dual_stack = expect_bool_or_null(tokens.next())?;
         377  +
                            }
         378  +
                            "implicitGlobalRegion" => {
         379  +
                                builder.implicit_global_region = token_to_str(tokens.next())?;
         380  +
                            }
         381  +
                            _ => skip_value(tokens)?,
         382  +
                        },
         383  +
                        other => return Err(DeserializeError::custom(format!("expected object key or end object, found: {other:?}",))),
         384  +
                    }
         385  +
                }
         386  +
                Ok(Some(builder))
         387  +
            }
         388  +
            _ => Err(DeserializeError::custom("expected start object")),
         389  +
        }
         390  +
    }
         391  +
}
         392  +
         393  +
#[cfg(test)]
         394  +
mod test {
         395  +
    use crate::endpoint_lib::diagnostic::DiagnosticCollector;
         396  +
    use crate::endpoint_lib::partition::{Partition, PartitionMetadata, PartitionOutput, PartitionOutputOverride, PartitionResolver};
         397  +
    use regex_lite::Regex;
         398  +
    use std::collections::HashMap;
         399  +
         400  +
    fn resolve<'a>(resolver: &'a PartitionResolver, region: &str) -> Partition<'a> {
         401  +
        resolver
         402  +
            .resolve_partition(region, &mut DiagnosticCollector::new())
         403  +
            .expect("could not resolve partition")
         404  +
    }
         405  +
         406  +
    #[test]
         407  +
    fn deserialize_partitions() {
         408  +
        let partitions = r#"{
         409  +
  "version": "1.1",
         410  +
  "partitions": [
         411  +
    {
         412  +
      "id": "aws",
         413  +
      "regionRegex": "^(us|eu|ap|sa|ca|me|af)-\\w+-\\d+$",
         414  +
      "regions": {
         415  +
        "af-south-1": {},
         416  +
        "af-east-1": {},
         417  +
        "ap-northeast-1": {},
         418  +
        "ap-northeast-2": {},
         419  +
        "ap-northeast-3": {},
         420  +
        "ap-south-1": {},
         421  +
        "ap-southeast-1": {},
         422  +
        "ap-southeast-2": {},
         423  +
        "ap-southeast-3": {},
         424  +
        "ca-central-1": {},
         425  +
        "eu-central-1": {},
         426  +
        "eu-north-1": {},
         427  +
        "eu-south-1": {},
         428  +
        "eu-west-1": {},
         429  +
        "eu-west-2": {},
         430  +
        "eu-west-3": {},
         431  +
        "me-south-1": {},
         432  +
        "sa-east-1": {},
         433  +
        "us-east-1": {},
         434  +
        "us-east-2": {},
         435  +
        "us-west-1": {},
         436  +
        "us-west-2": {},
         437  +
        "aws-global": {}
         438  +
      },
         439  +
      "outputs": {
         440  +
        "name": "aws",
         441  +
        "dnsSuffix": "amazonaws.com",
         442  +
        "dualStackDnsSuffix": "api.aws",
         443  +
        "supportsFIPS": true,
         444  +
        "supportsDualStack": true,
         445  +
        "implicitGlobalRegion": "us-east-1"
         446  +
      }
         447  +
    },
         448  +
    {
         449  +
      "id": "aws-us-gov",
         450  +
      "regionRegex": "^us\\-gov\\-\\w+\\-\\d+$",
         451  +
      "regions": {
         452  +
        "us-gov-west-1": {},
         453  +
        "us-gov-east-1": {},
         454  +
        "aws-us-gov-global": {}
         455  +
      },
         456  +
      "outputs": {
         457  +
        "name": "aws-us-gov",
         458  +
        "dnsSuffix": "amazonaws.com",
         459  +
        "dualStackDnsSuffix": "api.aws",
         460  +
        "supportsFIPS": true,
         461  +
        "supportsDualStack": true,
         462  +
        "implicitGlobalRegion": "us-gov-east-1"
         463  +
      }
         464  +
    },
         465  +
    {
         466  +
      "id": "aws-cn",
         467  +
      "regionRegex": "^cn\\-\\w+\\-\\d+$",
         468  +
      "regions": {
         469  +
        "cn-north-1": {},
         470  +
        "cn-northwest-1": {},
         471  +
        "aws-cn-global": {}
         472  +
      },
         473  +
      "outputs": {
         474  +
        "name": "aws-cn",
         475  +
        "dnsSuffix": "amazonaws.com.cn",
         476  +
        "dualStackDnsSuffix": "api.amazonwebservices.com.cn",
         477  +
        "supportsFIPS": true,
         478  +
        "supportsDualStack": true,
         479  +
        "implicitGlobalRegion": "cn-north-1"
         480  +
      }
         481  +
    },
         482  +
    {
         483  +
      "id": "aws-iso",
         484  +
      "regionRegex": "^us\\-iso\\-\\w+\\-\\d+$",
         485  +
      "outputs": {
         486  +
        "name": "aws-iso",
         487  +
        "dnsSuffix": "c2s.ic.gov",
         488  +
        "supportsFIPS": true,
         489  +
        "supportsDualStack": false,
         490  +
        "dualStackDnsSuffix": "c2s.ic.gov",
         491  +
        "implicitGlobalRegion": "us-iso-foo-1"
         492  +
      },
         493  +
      "regions": {}
         494  +
    },
         495  +
    {
         496  +
      "id": "aws-iso-b",
         497  +
      "regionRegex": "^us\\-isob\\-\\w+\\-\\d+$",
         498  +
      "outputs": {
         499  +
        "name": "aws-iso-b",
         500  +
        "dnsSuffix": "sc2s.sgov.gov",
         501  +
        "supportsFIPS": true,
         502  +
        "supportsDualStack": false,
         503  +
        "dualStackDnsSuffix": "sc2s.sgov.gov",
         504  +
        "implicitGlobalRegion": "us-isob-foo-1"
         505  +
      },
         506  +
      "regions": {}
         507  +
    }
         508  +
  ]
         509  +
}"#;
         510  +
        let resolver = super::deser::deserialize_partitions(partitions.as_bytes()).expect("valid resolver");
         511  +
        assert_eq!(resolve(&resolver, "cn-north-1").name, "aws-cn");
         512  +
        assert_eq!(resolve(&resolver, "cn-north-1").dns_suffix, "amazonaws.com.cn");
         513  +
        assert_eq!(resolver.partitions.len(), 5);
         514  +
        assert_eq!(resolve(&resolver, "af-south-1").implicit_global_region, "us-east-1");
         515  +
    }
         516  +
         517  +
    #[test]
         518  +
    fn resolve_partitions() {
         519  +
        let mut resolver = PartitionResolver::empty();
         520  +
        let new_suffix = PartitionOutputOverride {
         521  +
            dns_suffix: Some("mars.aws".into()),
         522  +
            ..Default::default()
         523  +
        };
         524  +
        resolver.add_partition(PartitionMetadata {
         525  +
            id: "aws".into(),
         526  +
            region_regex: Regex::new("^(us|eu|ap|sa|ca|me|af)-\\w+-\\d+$").unwrap(),
         527  +
            regions: HashMap::from([("mars-east-2".into(), new_suffix)]),
         528  +
            outputs: PartitionOutput {
         529  +
                name: "aws".into(),
         530  +
                dns_suffix: "amazonaws.com".into(),
         531  +
                dual_stack_dns_suffix: "api.aws".into(),
         532  +
                supports_fips: true,
         533  +
                supports_dual_stack: true,
         534  +
                implicit_global_region: "us-east-1".into(),
         535  +
            },
         536  +
        });
         537  +
        resolver.add_partition(PartitionMetadata {
         538  +
            id: "other".into(),
         539  +
            region_regex: Regex::new("^(other)-\\w+-\\d+$").unwrap(),
         540  +
            regions: Default::default(),
         541  +
            outputs: PartitionOutput {
         542  +
                name: "other".into(),
         543  +
                dns_suffix: "other.amazonaws.com".into(),
         544  +
                dual_stack_dns_suffix: "other.aws".into(),
         545  +
                supports_fips: false,
         546  +
                supports_dual_stack: true,
         547  +
                implicit_global_region: "other-south-2".into(),
         548  +
            },
         549  +
        });
         550  +
        assert_eq!(resolve(&resolver, "us-east-1").name, "aws");
         551  +
        assert_eq!(resolve(&resolver, "other-west-2").name, "other");
         552  +
        // mars-east-1 hits aws through the default fallback
         553  +
        assert_eq!(resolve(&resolver, "mars-east-1").dns_suffix, "amazonaws.com");
         554  +
        // mars-east-2 hits aws through the region override
         555  +
        assert_eq!(resolve(&resolver, "mars-east-2").dns_suffix, "mars.aws");
         556  +
    }
         557  +
}

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/error.rs

@@ -0,1 +0,13 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
pub use ::aws_smithy_runtime_api::box_error::BoxError;
           3  +
           4  +
/// Error type returned by the client.
           5  +
pub type SdkError<E, R = ::aws_smithy_runtime_api::client::orchestrator::HttpResponse> = ::aws_smithy_runtime_api::client::result::SdkError<E, R>;
           6  +
pub use ::aws_smithy_runtime_api::client::result::ConnectorError;
           7  +
pub use ::aws_smithy_types::error::operation::BuildError;
           8  +
           9  +
pub use ::aws_smithy_types::error::display::DisplayErrorContext;
          10  +
pub use ::aws_smithy_types::error::metadata::ErrorMetadata;
          11  +
pub use ::aws_smithy_types::error::metadata::ProvideErrorMetadata;
          12  +
          13  +
pub(crate) mod sealed_unhandled;

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/error/sealed_unhandled.rs

@@ -0,1 +0,20 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
/// This struct is not intended to be used.
           3  +
///
           4  +
/// This struct holds information about an unhandled error,
           5  +
/// but that information should be obtained by using the
           6  +
/// [`ProvideErrorMetadata`](::aws_smithy_types::error::metadata::ProvideErrorMetadata) trait
           7  +
/// on the error type.
           8  +
///
           9  +
/// This struct intentionally doesn't yield any useful information itself.
          10  +
#[deprecated(note = "Matching `Unhandled` directly is not forwards compatible. Instead, match using a \
          11  +
variable wildcard pattern and check `.code()`:
          12  +
 \
          13  +
&nbsp;&nbsp;&nbsp;`err if err.code() == Some(\"SpecificExceptionCode\") => { /* handle the error */ }`
          14  +
 \
          15  +
See [`ProvideErrorMetadata`](::aws_smithy_types::error::metadata::ProvideErrorMetadata) for what information is available for the error.")]
          16  +
#[derive(Debug)]
          17  +
pub struct Unhandled {
          18  +
    pub(crate) source: ::aws_smithy_runtime_api::box_error::BoxError,
          19  +
    pub(crate) meta: ::aws_smithy_types::error::metadata::ErrorMetadata,
          20  +
}

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/error_meta.rs

@@ -0,1 +0,119 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
/// All possible error types for this service.
           3  +
#[non_exhaustive]
           4  +
#[derive(::std::fmt::Debug)]
           5  +
pub enum Error {
           6  +
    /// <p>Returned if the request is malformed or contains an error such as an invalid parameter value or a missing required parameter.</p>
           7  +
    BadRequestException(crate::types::error::BadRequestException),
           8  +
    /// <p>Returned when the request exceeds the processing capacity of the ledger.</p>
           9  +
    CapacityExceededException(crate::types::error::CapacityExceededException),
          10  +
    /// <p>Returned if the session doesn't exist anymore because it timed out or expired.</p>
          11  +
    InvalidSessionException(crate::types::error::InvalidSessionException),
          12  +
    /// <p>Returned if a resource limit such as number of active sessions is exceeded.</p>
          13  +
    LimitExceededException(crate::types::error::LimitExceededException),
          14  +
    /// <p>Returned when a transaction cannot be written to the journal due to a failure in the verification phase of <i>optimistic concurrency control</i> (OCC).</p>
          15  +
    OccConflictException(crate::types::error::OccConflictException),
          16  +
    /// <p>Returned when the rate of requests exceeds the allowed throughput.</p>
          17  +
    RateExceededException(crate::types::error::RateExceededException),
          18  +
    /// An unexpected error occurred (e.g., invalid JSON returned by the service or an unknown error code).
          19  +
    #[deprecated(note = "Matching `Unhandled` directly is not forwards compatible. Instead, match using a \
          20  +
    variable wildcard pattern and check `.code()`:
          21  +
     \
          22  +
    &nbsp;&nbsp;&nbsp;`err if err.code() == Some(\"SpecificExceptionCode\") => { /* handle the error */ }`
          23  +
     \
          24  +
    See [`ProvideErrorMetadata`](#impl-ProvideErrorMetadata-for-Error) for what information is available for the error.")]
          25  +
    Unhandled(crate::error::sealed_unhandled::Unhandled),
          26  +
}
          27  +
impl ::std::fmt::Display for Error {
          28  +
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
          29  +
        match self {
          30  +
            Error::BadRequestException(inner) => inner.fmt(f),
          31  +
            Error::CapacityExceededException(inner) => inner.fmt(f),
          32  +
            Error::InvalidSessionException(inner) => inner.fmt(f),
          33  +
            Error::LimitExceededException(inner) => inner.fmt(f),
          34  +
            Error::OccConflictException(inner) => inner.fmt(f),
          35  +
            Error::RateExceededException(inner) => inner.fmt(f),
          36  +
            Error::Unhandled(_) => {
          37  +
                if let ::std::option::Option::Some(code) = ::aws_smithy_types::error::metadata::ProvideErrorMetadata::code(self) {
          38  +
                    write!(f, "unhandled error ({code})")
          39  +
                } else {
          40  +
                    f.write_str("unhandled error")
          41  +
                }
          42  +
            }
          43  +
        }
          44  +
    }
          45  +
}
          46  +
impl From<::aws_smithy_types::error::operation::BuildError> for Error {
          47  +
    fn from(value: ::aws_smithy_types::error::operation::BuildError) -> Self {
          48  +
        Error::Unhandled(crate::error::sealed_unhandled::Unhandled {
          49  +
            source: value.into(),
          50  +
            meta: ::std::default::Default::default(),
          51  +
        })
          52  +
    }
          53  +
}
          54  +
impl ::aws_smithy_types::error::metadata::ProvideErrorMetadata for Error {
          55  +
    fn meta(&self) -> &::aws_smithy_types::error::metadata::ErrorMetadata {
          56  +
        match self {
          57  +
            Self::BadRequestException(inner) => inner.meta(),
          58  +
            Self::CapacityExceededException(inner) => inner.meta(),
          59  +
            Self::InvalidSessionException(inner) => inner.meta(),
          60  +
            Self::LimitExceededException(inner) => inner.meta(),
          61  +
            Self::OccConflictException(inner) => inner.meta(),
          62  +
            Self::RateExceededException(inner) => inner.meta(),
          63  +
            Self::Unhandled(inner) => &inner.meta,
          64  +
        }
          65  +
    }
          66  +
}
          67  +
impl<R> From<::aws_smithy_runtime_api::client::result::SdkError<crate::operation::send_command::SendCommandError, R>> for Error
          68  +
where
          69  +
    R: Send + Sync + std::fmt::Debug + 'static,
          70  +
{
          71  +
    fn from(err: ::aws_smithy_runtime_api::client::result::SdkError<crate::operation::send_command::SendCommandError, R>) -> Self {
          72  +
        match err {
          73  +
            ::aws_smithy_runtime_api::client::result::SdkError::ServiceError(context) => Self::from(context.into_err()),
          74  +
            _ => Error::Unhandled(crate::error::sealed_unhandled::Unhandled {
          75  +
                meta: ::aws_smithy_types::error::metadata::ProvideErrorMetadata::meta(&err).clone(),
          76  +
                source: err.into(),
          77  +
            }),
          78  +
        }
          79  +
    }
          80  +
}
          81  +
impl From<crate::operation::send_command::SendCommandError> for Error {
          82  +
    fn from(err: crate::operation::send_command::SendCommandError) -> Self {
          83  +
        match err {
          84  +
            crate::operation::send_command::SendCommandError::BadRequestException(inner) => Error::BadRequestException(inner),
          85  +
            crate::operation::send_command::SendCommandError::CapacityExceededException(inner) => Error::CapacityExceededException(inner),
          86  +
            crate::operation::send_command::SendCommandError::InvalidSessionException(inner) => Error::InvalidSessionException(inner),
          87  +
            crate::operation::send_command::SendCommandError::LimitExceededException(inner) => Error::LimitExceededException(inner),
          88  +
            crate::operation::send_command::SendCommandError::OccConflictException(inner) => Error::OccConflictException(inner),
          89  +
            crate::operation::send_command::SendCommandError::RateExceededException(inner) => Error::RateExceededException(inner),
          90  +
            crate::operation::send_command::SendCommandError::Unhandled(inner) => Error::Unhandled(inner),
          91  +
        }
          92  +
    }
          93  +
}
          94  +
impl ::std::error::Error for Error {
          95  +
    fn source(&self) -> std::option::Option<&(dyn ::std::error::Error + 'static)> {
          96  +
        match self {
          97  +
            Error::BadRequestException(inner) => inner.source(),
          98  +
            Error::CapacityExceededException(inner) => inner.source(),
          99  +
            Error::InvalidSessionException(inner) => inner.source(),
         100  +
            Error::LimitExceededException(inner) => inner.source(),
         101  +
            Error::OccConflictException(inner) => inner.source(),
         102  +
            Error::RateExceededException(inner) => inner.source(),
         103  +
            Error::Unhandled(inner) => ::std::option::Option::Some(&*inner.source),
         104  +
        }
         105  +
    }
         106  +
}
         107  +
impl ::aws_types::request_id::RequestId for Error {
         108  +
    fn request_id(&self) -> Option<&str> {
         109  +
        match self {
         110  +
            Self::BadRequestException(e) => e.request_id(),
         111  +
            Self::CapacityExceededException(e) => e.request_id(),
         112  +
            Self::InvalidSessionException(e) => e.request_id(),
         113  +
            Self::LimitExceededException(e) => e.request_id(),
         114  +
            Self::OccConflictException(e) => e.request_id(),
         115  +
            Self::RateExceededException(e) => e.request_id(),
         116  +
            Self::Unhandled(e) => e.meta.request_id(),
         117  +
        }
         118  +
    }
         119  +
}

tmp-codegen-diff/aws-sdk/sdk/qldbsession/src/json_errors.rs

@@ -0,1 +0,180 @@
           1  +
// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
           2  +
/*
           3  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           4  +
 * SPDX-License-Identifier: Apache-2.0
           5  +
 */
           6  +
           7  +
use aws_smithy_json::deserialize::token::skip_value;
           8  +
use aws_smithy_json::deserialize::{error::DeserializeError, json_token_iter, Token};
           9  +
use aws_smithy_runtime_api::http::Headers;
          10  +
use aws_smithy_types::error::metadata::{Builder as ErrorMetadataBuilder, ErrorMetadata};
          11  +
use std::borrow::Cow;
          12  +
          13  +
// currently only used by AwsJson
          14  +
#[allow(unused)]
          15  +
pub fn is_error<B>(response: &http::Response<B>) -> bool {
          16  +
    !response.status().is_success()
          17  +
}
          18  +
          19  +
fn sanitize_error_code(error_code: &str) -> &str {
          20  +
    // Trim a trailing URL from the error code, which is done by removing the longest suffix
          21  +
    // beginning with a `:`
          22  +
    let error_code = match error_code.find(':') {
          23  +
        Some(idx) => &error_code[..idx],
          24  +
        None => error_code,
          25  +
    };
          26  +
          27  +
    // Trim a prefixing namespace from the error code, beginning with a `#`
          28  +
    match error_code.find('#') {
          29  +
        Some(idx) => &error_code[idx + 1..],
          30  +
        None => error_code,
          31  +
    }
          32  +
}
          33  +
          34  +
struct ErrorBody<'a> {
          35  +
    code: Option<Cow<'a, str>>,
          36  +
    message: Option<Cow<'a, str>>,
          37  +
}
          38  +
          39  +
fn parse_error_body(bytes: &[u8]) -> Result<ErrorBody<'_>, DeserializeError> {
          40  +
    let mut tokens = json_token_iter(bytes).peekable();
          41  +
    let (mut typ, mut code, mut message) = (None, None, None);
          42  +
    if let Some(Token::StartObject { .. }) = tokens.next().transpose()? {
          43  +
        loop {
          44  +
            match tokens.next().transpose()? {
          45  +
                Some(Token::EndObject { .. }) => break,
          46  +
                Some(Token::ObjectKey { key, .. }) => {
          47  +
                    if let Some(Ok(Token::ValueString { value, .. })) = tokens.peek() {
          48  +
                        match key.as_escaped_str() {
          49  +
                            "code" => code = Some(value.to_unescaped()?),
          50  +
                            "__type" => typ = Some(value.to_unescaped()?),
          51  +
                            "message" | "Message" | "errorMessage" => message = Some(value.to_unescaped()?),
          52  +
                            _ => {}
          53  +
                        }
          54  +
                    }
          55  +
                    skip_value(&mut tokens)?;
          56  +
                }
          57  +
                _ => return Err(DeserializeError::custom("expected object key or end object")),
          58  +
            }
          59  +
        }
          60  +
        if tokens.next().is_some() {
          61  +
            return Err(DeserializeError::custom("found more JSON tokens after completing parsing"));
          62  +
        }
          63  +
    }
          64  +
    Ok(ErrorBody { code: code.or(typ), message })
          65  +
}
          66  +
          67  +
pub fn parse_error_metadata(payload: &[u8], headers: &Headers) -> Result<ErrorMetadataBuilder, DeserializeError> {
          68  +
    let ErrorBody { code, message } = parse_error_body(payload)?;
          69  +
          70  +
    let mut err_builder = ErrorMetadata::builder();
          71  +
    if let Some(code) = headers.get("x-amzn-errortype").or(code.as_deref()).map(sanitize_error_code) {
          72  +
        err_builder = err_builder.code(code);
          73  +
    }
          74  +
    if let Some(message) = message {
          75  +
        err_builder = err_builder.message(message);
          76  +
    }
          77  +
    Ok(err_builder)
          78  +
}
          79  +
          80  +
#[cfg(test)]
          81  +
mod test {
          82  +
    use crate::json_errors::{parse_error_body, parse_error_metadata, sanitize_error_code};
          83  +
    use aws_smithy_runtime_api::client::orchestrator::HttpResponse;
          84  +
    use aws_smithy_types::{body::SdkBody, error::ErrorMetadata};
          85  +
    use std::borrow::Cow;
          86  +
          87  +
    #[test]
          88  +
    fn error_metadata() {
          89  +
        let response = HttpResponse::try_from(
          90  +
            http::Response::builder()
          91  +
                .body(SdkBody::from(r#"{ "__type": "FooError", "message": "Go to foo" }"#))
          92  +
                .unwrap(),
          93  +
        )
          94  +
        .unwrap();
          95  +
        assert_eq!(
          96  +
            parse_error_metadata(response.body().bytes().unwrap(), response.headers())
          97  +
                .unwrap()
          98  +
                .build(),
          99  +
            ErrorMetadata::builder().code("FooError").message("Go to foo").build()
         100  +
        )
         101  +
    }
         102  +
         103  +
    #[test]
         104  +
    fn error_type() {
         105  +
        assert_eq!(
         106  +
            Some(Cow::Borrowed("FooError")),
         107  +
            parse_error_body(br#"{ "__type": "FooError" }"#).unwrap().code
         108  +
        );
         109  +
    }
         110  +
         111  +
    #[test]
         112  +
    fn code_takes_priority() {
         113  +
        assert_eq!(
         114  +
            Some(Cow::Borrowed("BarError")),
         115  +
            parse_error_body(br#"{ "code": "BarError", "__type": "FooError" }"#).unwrap().code
         116  +
        );
         117  +
    }
         118  +
         119  +
    #[test]
         120  +
    fn ignore_unrecognized_fields() {
         121  +
        assert_eq!(
         122  +
            Some(Cow::Borrowed("FooError")),
         123  +
            parse_error_body(br#"{ "__type": "FooError", "asdf": 5, "fdsa": {}, "foo": "1" }"#)
         124  +
                .unwrap()
         125  +
                .code
         126  +
        );
         127  +
    }
         128  +
         129  +
    #[test]
         130  +
    fn sanitize_namespace_and_url() {
         131  +
        assert_eq!(
         132  +
            sanitize_error_code("aws.protocoltests.restjson#FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/"),
         133  +
            "FooError"
         134  +
        );
         135  +
    }
         136  +
         137  +
    #[test]
         138  +
    fn sanitize_noop() {
         139  +
        assert_eq!(sanitize_error_code("FooError"), "FooError");
         140  +
    }
         141  +
         142  +
    #[test]
         143  +
    fn sanitize_url() {
         144  +
        assert_eq!(
         145  +
            sanitize_error_code("FooError:http://internal.amazon.com/coral/com.amazon.coral.validate/"),
         146  +
            "FooError"
         147  +
        );
         148  +
    }
         149  +
         150  +
    #[test]
         151  +
    fn sanitize_namespace() {
         152  +
        assert_eq!(sanitize_error_code("aws.protocoltests.restjson#FooError"), "FooError");
         153  +
    }
         154  +
         155  +
    // services like lambda use an alternate `Message` instead of `message`
         156  +
    #[test]
         157  +
    fn alternative_error_message_names() {
         158  +
        let response = HttpResponse::try_from(
         159  +
            http::Response::builder()
         160  +
                .header("x-amzn-errortype", "ResourceNotFoundException")
         161  +
                .body(SdkBody::from(
         162  +
                    r#"{
         163  +
                    "Type": "User",
         164  +
                    "Message": "Functions from 'us-west-2' are not reachable from us-east-1"
         165  +
                }"#,
         166  +
                ))
         167  +
                .unwrap(),
         168  +
        )
         169  +
        .unwrap();
         170  +
        assert_eq!(
         171  +
            parse_error_metadata(response.body().bytes().unwrap(), response.headers())
         172  +
                .unwrap()
         173  +
                .build(),
         174  +
            ErrorMetadata::builder()
         175  +
                .code("ResourceNotFoundException")
         176  +
                .message("Functions from 'us-west-2' are not reachable from us-east-1")
         177  +
                .build()
         178  +
        );
         179  +
    }
         180  +
}