Unverified Commit 9f905179 authored by david-perez's avatar david-perez Committed by GitHub
Browse files

Support `@sparse` constrained map shapes and list shapes (#2213)

Turns out we've never supported them, neither directly constrained nor
with constrained members, because of a lack of tests. Yet another data
point to prioritize working on code-generating `constraints.smithy` (see
https://github.com/awslabs/smithy-rs/issues/2101).

The implementation is simple: we just need to call the symbol provider
on the member symbols instead of on the target symbols so we get
`Option<T>` list members / map values if applicable, and handle the
wrapper when converting between unconstrained and constrained types with
help from `match` and `Option<T>::map`.
parent 93f4c4f0
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -10,3 +10,9 @@
# references = ["smithy-rs#920"]
# meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"}
# author = "rcoh"

[[smithy-rs]]
message = "`@sparse` list shapes and map shapes with constraint traits and with constrained members are now supported"
references = ["smithy-rs#2213"]
meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "server"}
author = "david-perez"
+28 −0
Original line number Diff line number Diff line
@@ -481,6 +481,10 @@ structure ConA {
    lengthMap: LengthMap,

    mapOfMapOfListOfListOfConB: MapOfMapOfListOfListOfConB,
    sparseMap: SparseMap,
    sparseList: SparseList,
    sparseLengthMap: SparseLengthMap,
    sparseLengthList: SparseLengthList,

    constrainedUnion: ConstrainedUnion,
    enumString: EnumString,
@@ -543,6 +547,30 @@ structure ConA {
    // lengthSetOfPatternString: LengthSetOfPatternString,
}

@sparse
map SparseMap {
    key: String,
    value: LengthString
}

@sparse
list SparseList {
    member: LengthString
}

@sparse
@length(min: 69)
map SparseLengthMap {
    key: String,
    value: String
}

@sparse
@length(min: 69)
list SparseLengthList {
    member: String
}

map MapOfLengthBlob {
    key: String,
    value: LengthBlob,
+0 −3
Original line number Diff line number Diff line
@@ -97,9 +97,6 @@ class PubCrateConstrainedShapeSymbolProvider(
            }

            is MemberShape -> {
                require(model.expectShape(shape.container).isStructureShape) {
                    "This arm is only exercised by `ServerBuilderGenerator`"
                }
                require(!shape.hasConstraintTraitOrTargetHasConstraintTrait(model, base)) { errorMessage(shape) }

                val targetShape = model.expectShape(shape.target)
+2 −2
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ class ConstrainedCollectionGenerator(
        }

        val name = constrainedShapeSymbolProvider.toSymbol(shape).name
        val inner = "std::vec::Vec<#{ValueSymbol}>"
        val inner = "std::vec::Vec<#{ValueMemberSymbol}>"
        val constraintViolation = constraintViolationSymbolProvider.toSymbol(shape)
        val constrainedTypeVisibility = Visibility.publicIf(publicConstrainedTypes, Visibility.PUBCRATE)
        val constrainedTypeMetadata = RustMetadata(
@@ -79,7 +79,7 @@ class ConstrainedCollectionGenerator(
        )

        val codegenScope = arrayOf(
            "ValueSymbol" to constrainedShapeSymbolProvider.toSymbol(model.expectShape(shape.member.target)),
            "ValueMemberSymbol" to constrainedShapeSymbolProvider.toSymbol(shape.member),
            "From" to RuntimeType.From,
            "TryFrom" to RuntimeType.TryFrom,
            "ConstraintViolation" to constraintViolation,
+2 −2
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ class ConstrainedMapGenerator(
        val lengthTrait = shape.expectTrait<LengthTrait>()

        val name = constrainedShapeSymbolProvider.toSymbol(shape).name
        val inner = "std::collections::HashMap<#{KeySymbol}, #{ValueSymbol}>"
        val inner = "std::collections::HashMap<#{KeySymbol}, #{ValueMemberSymbol}>"
        val constraintViolation = constraintViolationSymbolProvider.toSymbol(shape)

        val constrainedTypeVisibility = Visibility.publicIf(publicConstrainedTypes, Visibility.PUBCRATE)
@@ -69,7 +69,7 @@ class ConstrainedMapGenerator(

        val codegenScope = arrayOf(
            "KeySymbol" to constrainedShapeSymbolProvider.toSymbol(model.expectShape(shape.key.target)),
            "ValueSymbol" to constrainedShapeSymbolProvider.toSymbol(model.expectShape(shape.value.target)),
            "ValueMemberSymbol" to constrainedShapeSymbolProvider.toSymbol(shape.value),
            "From" to RuntimeType.From,
            "TryFrom" to RuntimeType.TryFrom,
            "ConstraintViolation" to constraintViolation,
Loading