Unverified Commit 64ccdccc authored by Matteo Bigoi's avatar Matteo Bigoi Committed by GitHub
Browse files

Use a single struct to represent the RequestExtension (#978)

parent d5750d48
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -327,10 +327,9 @@ class ServerProtocolTestGenerator(
        rustWriter.rust(
            """
            let extensions = http_request.extensions().expect("unable to extract http request extensions");
            let namespace = extensions.get::<aws_smithy_http_server::ExtensionNamespace>().expect("extension ExtensionNamespace not found");
            assert_eq!(**namespace, ${operationShape.id.getNamespace().dq()});
            let operation_name = extensions.get::<aws_smithy_http_server::ExtensionOperationName>().expect("extension ExtensionOperationName not found");
            assert_eq!(**operation_name, ${operationSymbol.name.dq()});
            let request_extensions = extensions.get::<aws_smithy_http_server::RequestExtensions>().expect("extension RequestExtensions not found");
            assert_eq!(request_extensions.namespace, ${operationShape.id.getNamespace().dq()});
            assert_eq!(request_extensions.operation_name, ${operationSymbol.name.dq()});
            """.trimIndent()
        )
    }
+39 −22
Original line number Diff line number Diff line
@@ -316,8 +316,7 @@ private class ServerHttpProtocolImplGenerator(
        val operationName = symbolProvider.toSymbol(operationShape).name
        return """
            let extensions = req.extensions_mut().ok_or(#{SmithyHttpServer}::rejection::ExtensionsAlreadyExtracted)?;
            extensions.insert(#{SmithyHttpServer}::ExtensionNamespace::new(${namespace.dq()}));
            extensions.insert(#{SmithyHttpServer}::ExtensionOperationName::new(${operationName.dq()}));
            extensions.insert(#{SmithyHttpServer}::RequestExtensions::new(${namespace.dq()}, ${operationName.dq()}));
        """.trimIndent()
    }

@@ -640,11 +639,13 @@ private class ServerHttpProtocolImplGenerator(
        } else if (targetMapValue.isSetShape) {
            QueryParamsTargetMapValueType.SET
        } else {
            throw ExpectationNotMetException("""
            throw ExpectationNotMetException(
                """
                @httpQueryParams trait applied to non-supported target
                $targetMapValue of type ${targetMapValue.type}
                """.trimIndent(),
                targetMapValue.sourceLocation)
                targetMapValue.sourceLocation
            )
        }

    private fun serverRenderQueryStringParser(writer: RustWriter, operationShape: OperationShape) {
@@ -669,7 +670,8 @@ private class ServerHttpProtocolImplGenerator(
        }

        with(writer) {
            rustTemplate("""
            rustTemplate(
                """
                let query_string = request.uri().query().ok_or(#{SmithyHttpServer}::rejection::MissingQueryString)?;
                let pairs = #{SerdeUrlEncoded}::from_str::<Vec<(&str, &str)>>(query_string)?;
                """.trimIndent(),
@@ -677,7 +679,8 @@ private class ServerHttpProtocolImplGenerator(
            )

            if (queryParamsBinding != null) {
                rustTemplate("let mut query_params: #{HashMap}<String, " +
                rustTemplate(
                    "let mut query_params: #{HashMap}<String, " +
                        "${queryParamsBinding.queryParamsBindingTargetMapValueType().asRustType().render()}> = #{HashMap}::new();",
                    "HashMap" to RustType.HashMap.RuntimeType,
                )
@@ -694,7 +697,8 @@ private class ServerHttpProtocolImplGenerator(
            rustBlock("for (k, v) in pairs") {
                queryBindingsTargettingSimple.forEach {
                    val deserializer = generateParsePercentEncodedStrFn(it)
                    rustTemplate("""
                    rustTemplate(
                        """
                        if !seen_${it.memberName.toSnakeCase()} && k == "${it.locationName}" {
                            input = input.${it.member.setterName()}(
                                #{deserializer}(v)?
@@ -702,7 +706,8 @@ private class ServerHttpProtocolImplGenerator(
                            seen_${it.memberName.toSnakeCase()} = true;
                        }
                        """.trimIndent(),
                    "deserializer" to deserializer)
                        "deserializer" to deserializer
                    )
                }
                queryBindingsTargettingCollection.forEach {
                    rustBlock("if k == ${it.locationName.dq()}") {
@@ -714,9 +719,12 @@ private class ServerHttpProtocolImplGenerator(
                                // `<_>::from()` is necessary to convert the `&str` into:
                                //     * the Rust enum in case the `string` shape has the `enum` trait; or
                                //     * `String` in case it doesn't.
                                rustTemplate("""
                                rustTemplate(
                                    """
                                    let v = <_>::from(#{PercentEncoding}::percent_decode_str(v).decode_utf8()?.as_ref());
                                """.trimIndent(), *codegenScope)
                                    """.trimIndent(),
                                    *codegenScope
                                )
                            }
                            memberShape.isTimestampShape -> {
                                val index = HttpBindingIndex.of(model)
@@ -727,7 +735,8 @@ private class ServerHttpProtocolImplGenerator(
                                        protocol.defaultTimestampFormat,
                                    )
                                val timestampFormatType = RuntimeType.TimestampFormat(runtimeConfig, timestampFormat)
                                rustTemplate("""
                                rustTemplate(
                                    """
                                    let v = #{PercentEncoding}::percent_decode_str(v).decode_utf8()?;
                                    let v = #{DateTime}::from_str(&v, #{format})?;
                                    """.trimIndent(),
@@ -736,9 +745,12 @@ private class ServerHttpProtocolImplGenerator(
                                )
                            }
                            else -> { // Number or boolean.
                                rust("""
                                rust(
                                    """
                                    let v = <_ as #T>::parse_smithy_primitive(v)?;
                                """.trimIndent(), CargoDependency.SmithyTypes(runtimeConfig).asType().member("primitive::Parse"))
                                    """.trimIndent(),
                                    CargoDependency.SmithyTypes(runtimeConfig).asType().member("primitive::Parse")
                                )
                            }
                        }
                        rust("${it.memberName.toSnakeCase()}.push(v);")
@@ -750,10 +762,12 @@ private class ServerHttpProtocolImplGenerator(
                        QueryParamsTargetMapValueType.STRING -> {
                            rust("query_params.entry(String::from(k)).or_insert_with(|| String::from(v));")
                        } else -> {
                            rustTemplate("""
                            rustTemplate(
                                """
                                let entry = query_params.entry(String::from(k)).or_default();
                                entry.push(String::from(v));
                            """.trimIndent())
                                """.trimIndent()
                            )
                        }
                    }
                }
@@ -762,9 +776,11 @@ private class ServerHttpProtocolImplGenerator(
                rust("input = input.${queryParamsBinding.member.setterName()}(Some(query_params));")
            }
            queryBindingsTargettingCollection.forEach {
                rustTemplate("""
                rustTemplate(
                    """
                    input = input.${it.member.setterName()}(Some(${it.memberName.toSnakeCase()}));
                """.trimIndent())
                    """.trimIndent()
                )
            }
        }
    }
@@ -810,7 +826,8 @@ private class ServerHttpProtocolImplGenerator(
                // `<_>::from()` is necessary to convert the `&str` into:
                //     * the Rust enum in case the `string` shape has the `enum` trait; or
                //     * `String` in case it doesn't.
                rustTemplate("""
                rustTemplate(
                    """
                    let value = <_>::from(#{PercentEncoding}::percent_decode_str(value).decode_utf8()?.as_ref());
                    Ok(Some(value))
                    """.trimIndent(),
+0 −6
Original line number Diff line number Diff line
edition = "2018"
max_width = 120
# The "Default" setting has a heuristic which splits lines too aggresively.
# We are willing to revisit this setting in future versions of rustfmt.
# Bugs:
#   * https://github.com/rust-lang/rustfmt/issues/3119
#   * https://github.com/rust-lang/rustfmt/issues/3120
use_small_heuristics = "Max"
# Prevent carriage returns
newline_style = "Unix"
+22 −8
Original line number Diff line number Diff line
@@ -39,15 +39,29 @@ use async_trait::async_trait;
use axum_core::extract::{FromRequest, RequestParts};
use std::ops::Deref;

/// Extension type used to store the Smithy model namespace.
#[derive(Debug, Clone)]
pub struct ExtensionNamespace(&'static str);
impl_extension_new_and_deref!(ExtensionNamespace);
/// Extension type used to store Smithy request information.
#[derive(Debug, Clone, Default, Copy)]
pub struct RequestExtensions {
    /// Smithy model namespace.
    pub namespace: &'static str,
    /// Smithy operation name.
    pub operation_name: &'static str,
}

/// Extension type used to store the Smithy operation name.
#[derive(Debug, Clone)]
pub struct ExtensionOperationName(&'static str);
impl_extension_new_and_deref!(ExtensionOperationName);
impl RequestExtensions {
    /// Generates a new `RequestExtensions`.
    pub fn new(namespace: &'static str, operation_name: &'static str) -> Self {
        Self {
            namespace,
            operation_name,
        }
    }

    /// Returns the current operation formatted as <namespace>#<operation_name>.
    pub fn operation(&self) -> String {
        format!("{}#{}", self.namespace, self.operation_name)
    }
}

/// Extension type used to store the type of user defined error returned by an operation.
/// These are modeled errors, defined in the Smithy model.
+1 −3
Original line number Diff line number Diff line
@@ -24,9 +24,7 @@ pub use self::body::{boxed, to_boxed, Body, BoxBody, HttpBody};
#[doc(inline)]
pub use self::error::Error;
#[doc(inline)]
pub use self::extension::{
    Extension, ExtensionModeledError, ExtensionNamespace, ExtensionOperationName, ExtensionRejection,
};
pub use self::extension::{Extension, ExtensionModeledError, ExtensionRejection, RequestExtensions};
#[doc(inline)]
pub use self::routing::Router;
#[doc(inline)]
Loading