Unverified Commit c049a37f authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

RestJson Response Parsing (#272)

* restJson1 Header Deserialization Support

This adds support for the `@httpHeader` trait during request deserialization. This is facilitated via a `Read` abstraction which allows parsers to consume part of an input and return the remaining input. We use this to enable things like `HttpDates` which actually include commas to be parsed in a comma delimited fashion.

The internal libraries may eventually be refactored to reduce the amount of generics if it proves to be a compiler bottleneck.

* Add support for parsing request bodies

* Add response code parsing

* Lots of refactorings to restJson response parsing

* Fix some clippy lints

* Add document deserialization support and delete the failing tests
parent b67e651f
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ service RestJsonExtras {
    }
])
operation EnumPayload {
    input: EnumPayloadInput
    input: EnumPayloadInput,
    output: EnumPayloadInput
}

structure EnumPayloadInput {
@@ -50,7 +51,8 @@ string StringEnum
    }
])
operation StringPayload {
    input: StringPayloadInput
    input: StringPayloadInput,
    output: StringPayloadInput
}

structure StringPayloadInput {
+1 −0
Original line number Diff line number Diff line
@@ -202,6 +202,7 @@ sealed class Attribute {
         */
        val NonExhaustive = Custom("non_exhaustive")
        val AllowUnused = Custom("allow(dead_code)")
        val AllowUnusedMut = Custom("allow(unused_mut)")
    }

    data class Derives(val derives: Set<RuntimeType>) : Attribute() {
+2 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ import software.amazon.smithy.rust.codegen.rustlang.InlineDependency
import software.amazon.smithy.rust.codegen.rustlang.RustDependency
import software.amazon.smithy.rust.codegen.rustlang.RustType
import software.amazon.smithy.rust.codegen.rustlang.RustWriter
import software.amazon.smithy.rust.codegen.rustlang.asType
import java.util.Optional

data class RuntimeConfig(val cratePrefix: String = "smithy", val relativePath: String = "../") {
@@ -125,6 +126,7 @@ data class RuntimeType(val name: String?, val dependency: RustDependency?, val n
                func, CargoDependency.ProtocolTestHelpers(runtimeConfig), "protocol_test_helpers"
            )

        val http = CargoDependency.Http.asType()
        fun Http(path: String): RuntimeType =
            RuntimeType(name = path, dependency = CargoDependency.Http, namespace = "http")

+1 −1
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ class SymbolVisitor(
        // an Input shape, then the field is _not optional_.
        val httpLabeledInput =
            container.hasTrait(SyntheticInputTrait::class.java) && member.hasTrait(HttpLabelTrait::class.java)
        return if (nullableIndex.isNullable(member) && !httpLabeledInput) {
        return if (nullableIndex.isNullable(member) && !httpLabeledInput || model.expectShape(member.target).isDocumentShape) {
            symbol.makeOptional()
        } else symbol
    }
+11 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import software.amazon.smithy.rust.codegen.smithy.RuntimeType
import software.amazon.smithy.rust.codegen.smithy.RustSymbolProvider
import software.amazon.smithy.rust.codegen.smithy.defaultValue
import software.amazon.smithy.rust.codegen.smithy.isOptional
import software.amazon.smithy.rust.codegen.smithy.letIf
import software.amazon.smithy.rust.codegen.smithy.makeOptional
import software.amazon.smithy.rust.codegen.smithy.rustType
import software.amazon.smithy.rust.codegen.util.dq
@@ -128,6 +129,9 @@ class OperationInputBuilderGenerator(
    }
}

/** setter names will never hit a reserved word and therefore never need escaping */
fun MemberShape.setterName(): String = "set_${this.memberName.toSnakeCase()}"

abstract class BuilderGenerator(
    val model: Model,
    private val symbolProvider: RustSymbolProvider,
@@ -194,6 +198,13 @@ abstract class BuilderGenerator(
                    write("self.$memberName = Some(${builderConverter(coreType)});")
                    write("self")
                }

                writer.rustBlock("pub fn ${member.setterName()}(mut self, inp: ${outerType.render(true)}) -> Self") {
                    val v = "inp".letIf(outerType !is RustType.Option) {
                        "Some($it)"
                    }
                    rust("self.$memberName = $v; self")
                }
            }

            buildFn(this)
Loading