From 703b6a465857cd77df91660c8ee8d1c54718846a Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 14:34:43 +0000 Subject: [PATCH 1/7] Group all override-related test cases together. --- .../protocol/ServerProtocolTestGenerator.kt | 111 ++++++++++-------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt index c8e40002bd..e73c3902fb 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/protocol/ServerProtocolTestGenerator.kt @@ -945,21 +945,65 @@ class ServerProtocolTestGenerator( // Tests involving constraint traits, which are not yet fully implemented. // See https://github.com/awslabs/smithy-rs/issues/1401. - FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case2", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlob_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlob_case1", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthList_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthList_case1", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapValue_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapValue_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloat_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloat_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloat", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloat", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedPatternSensitiveString", TestType.MalformedRequest), + + // See https://github.com/awslabs/smithy-rs/issues/1969 + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case0", TestType.MalformedRequest), + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case1", TestType.MalformedRequest), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeIntegerOverride_case0", + TestType.MalformedRequest, + ), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeIntegerOverride_case1", + TestType.MalformedRequest, + ), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeLongOverride_case0", + TestType.MalformedRequest, + ), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeLongOverride_case1", + TestType.MalformedRequest, + ), + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxShortOverride", TestType.MalformedRequest), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeMaxIntegerOverride", + TestType.MalformedRequest, + ), + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxLongOverride", TestType.MalformedRequest), + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinShortOverride", TestType.MalformedRequest), + FailingTest( + MalformedRangeValidation, + "RestJsonMalformedRangeMinIntegerOverride", + TestType.MalformedRequest, + ), + FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinLongOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthMaxStringOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthMinStringOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxByteOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloatOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinByteOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloatOverride", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedPatternListOverride_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedPatternListOverride_case1", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedPatternMapKeyOverride_case0", TestType.MalformedRequest), @@ -978,46 +1022,15 @@ class ServerProtocolTestGenerator( FailingTest(RestJsonValidation, "RestJsonMalformedPatternStringOverride_case1", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedPatternUnionOverride_case0", TestType.MalformedRequest), FailingTest(RestJsonValidation, "RestJsonMalformedPatternUnionOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByteOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloatOverride_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByte_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeByte_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloat_case0", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeFloat_case1", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMaxStringOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedLengthMinStringOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxByteOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloatOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinByteOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloatOverride", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxByte", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMaxFloat", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinByte", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedRangeMinFloat", TestType.MalformedRequest), - FailingTest(RestJsonValidation, "RestJsonMalformedPatternSensitiveString", TestType.MalformedRequest), - - // Tests involving using @range on bytes, shorts and longs. - // See https://github.com/awslabs/smithy-rs/issues/1968 - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeLong_case0", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeLong_case1", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxLong", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinLong", TestType.MalformedRequest), - - // See https://github.com/awslabs/smithy-rs/issues/1969 - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case0", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeShortOverride_case1", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeIntegerOverride_case0", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeIntegerOverride_case1", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeLongOverride_case0", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeLongOverride_case1", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxShortOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxIntegerOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMaxLongOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinShortOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinIntegerOverride", TestType.MalformedRequest), - FailingTest(MalformedRangeValidation, "RestJsonMalformedRangeMinLongOverride", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthBlobOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthListOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthMapOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case0", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case1", TestType.MalformedRequest), + FailingTest(RestJsonValidation, "RestJsonMalformedLengthStringOverride_case2", TestType.MalformedRequest), // Some tests for the S3 service (restXml). FailingTest("com.amazonaws.s3#AmazonS3", "GetBucketLocationUnwrappedOutput", TestType.Response), From 7ffc6e66b3929ef330a1c8c1ae1c88ef8892af3e Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 14:44:42 +0000 Subject: [PATCH 2/7] Add @range examples for both byte and long in constraints.smithy. --- .../common-test-models/constraints.smithy | 132 +++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/codegen-core/common-test-models/constraints.smithy b/codegen-core/common-test-models/constraints.smithy index d22ea9fcfc..322abf1d07 100644 --- a/codegen-core/common-test-models/constraints.smithy +++ b/codegen-core/common-test-models/constraints.smithy @@ -50,7 +50,7 @@ operation ConstrainedShapesOperation { } @http( - uri: "/constrained-http-bound-shapes-operation/{rangeIntegerLabel}/{rangeShortLabel}/{lengthStringLabel}/{enumStringLabel}", + uri: "/constrained-http-bound-shapes-operation/{rangeIntegerLabel}/{rangeShortLabel}/{rangeLongLabel}/{rangeByteLabel}/{lengthStringLabel}/{enumStringLabel}", method: "POST" ) operation ConstrainedHttpBoundShapesOperation { @@ -186,6 +186,14 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { @httpLabel rangeShortLabel: RangeShort, + @required + @httpLabel + rangeLongLabel: RangeLong, + + @required + @httpLabel + rangeByteLabel: RangeByte, + @required @httpLabel enumStringLabel: EnumString, @@ -203,6 +211,12 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { @httpHeader("X-Range-Short") rangeShortHeader: RangeShort, + @httpHeader("X-Range-Long") + rangeLongHeader: RangeLong, + + @httpHeader("X-Range-Byte") + rangeByteHeader: RangeByte, + // @httpHeader("X-Length-MediaType") // lengthStringHeaderWithMediaType: MediaTypeLengthString, @@ -220,6 +234,10 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { // rangeIntegerSetHeader: SetOfRangeInteger, // @httpHeader("X-Range-Short-Set") // rangeShortSetHeader: SetOfShortInteger, + // @httpHeader("X-Range-Long-Set") + // rangeLongSetHeader: SetOfRangeLong, + // @httpHeader("X-Range-Byte-Set") + // rangeByteSetHeader: SetOfByteInteger, @httpHeader("X-Range-Integer-List") rangeIntegerListHeader: ListOfRangeInteger, @@ -227,6 +245,12 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { @httpHeader("X-Range-Short-List") rangeShortListHeader: ListOfRangeShort, + @httpHeader("X-Range-Long-List") + rangeLongListHeader: ListOfRangeLong, + + @httpHeader("X-Range-Byte-List") + rangeByteListHeader: ListOfRangeByte, + // TODO(https://github.com/awslabs/smithy-rs/issues/1431) // @httpHeader("X-Enum") //enumStringHeader: EnumString, @@ -243,6 +267,12 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { @httpQuery("rangeShort") rangeShortQuery: RangeShort, + @httpQuery("rangeLong") + rangeLongQuery: RangeLong, + + @httpQuery("rangeByte") + rangeByteQuery: RangeByte, + @httpQuery("enumString") enumStringQuery: EnumString, @@ -260,12 +290,22 @@ structure ConstrainedHttpBoundShapesOperationInputOutput { @httpQuery("rangeShortList") rangeShortListQuery: ListOfRangeShort, + @httpQuery("rangeLongList") + rangeLongListQuery: ListOfRangeLong, + + @httpQuery("rangeByteList") + rangeByteListQuery: ListOfRangeByte, + // TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is // just a `list` shape with `uniqueItems`, which hasn't been implemented yet. // @httpQuery("rangeIntegerSet") // rangeIntegerSetQuery: SetOfRangeInteger, // @httpQuery("rangeShortSet") // rangeShortSetQuery: SetOfRangeShort, + // @httpQuery("rangeLongSet") + // rangeLongSetQuery: SetOfRangeLong, + // @httpQuery("rangeByteSet") + // rangeByteSetQuery: SetOfRangeByte, @httpQuery("enumStringList") enumStringListQuery: ListOfEnumString, @@ -392,6 +432,16 @@ structure ConA { maxRangeShort: MaxRangeShort, fixedValueShort: FixedValueShort, + rangeLong: RangeLong, + minRangeLong: MinRangeLong, + maxRangeLong: MaxRangeLong, + fixedValueLong: FixedValueLong, + + rangeByte: RangeByte, + minRangeByte: MinRangeByte, + maxRangeByte: MaxRangeByte, + fixedValueByte: FixedValueByte, + conBList: ConBList, conBList2: ConBList2, @@ -424,6 +474,18 @@ structure ConA { // setOfRangeShort: SetOfRangeShort, mapOfRangeShort: MapOfRangeShort, + listOfRangeLong: ListOfRangeLong, + // TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is + // just a `list` shape with `uniqueItems`, which hasn't been implemented yet. + // setOfRangeLong: SetOfRangeLong, + mapOfRangeLong: MapOfRangeLong, + + listOfRangeByte: ListOfRangeByte, + // TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is + // just a `list` shape with `uniqueItems`, which hasn't been implemented yet. + // setOfRangeByte: SetOfRangeByte, + mapOfRangeByte: MapOfRangeByte, + nonStreamingBlob: NonStreamingBlob patternString: PatternString, @@ -456,6 +518,16 @@ map MapOfRangeShort { value: RangeShort, } +map MapOfRangeLong { + key: String, + value: RangeLong, +} + +map MapOfRangeByte { + key: String, + value: RangeByte, +} + map MapOfEnumString { key: EnumString, value: EnumString, @@ -503,6 +575,20 @@ map MapOfSetOfLengthString { // value: SetOfRangeShort, // } +// TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is +// just a `list` shape with `uniqueItems`, which hasn't been implemented yet. +// map MapOfSetOfRangeLong { +// key: String, +// value: SetOfRangeLong, +// } + +// TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is +// just a `list` shape with `uniqueItems`, which hasn't been implemented yet. +// map MapOfSetOfRangeByte { +// key: String, +// value: SetOfRangeByte, +// } + @length(min: 2, max: 8) list LengthListOfLengthString { member: LengthString @@ -555,6 +641,30 @@ short MaxRangeShort @range(min: 10, max: 10) short FixedValueShort +@range(min: -0, max: 10) +long RangeLong + +@range(min: -10) +long MinRangeLong + +@range(max: 11) +long MaxRangeLong + +@range(min: 10, max: 10) +long FixedValueLong + +@range(min: -0, max: 10) +byte RangeByte + +@range(min: -10) +byte MinRangeByte + +@range(max: 11) +byte MaxRangeByte + +@range(min: 10, max: 10) +byte FixedValueByte + /// A union with constrained members. union ConstrainedUnion { enumString: EnumString, @@ -620,6 +730,26 @@ list ListOfRangeShort { member: RangeShort } +// TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is +// just a `list` shape with `uniqueItems`, which hasn't been implemented yet. +// set SetOfRangeLong { +// member: RangeLong +// } + +list ListOfRangeLong { + member: RangeLong +} + +// TODO(https://github.com/awslabs/smithy-rs/issues/1401): a `set` shape is +// just a `list` shape with `uniqueItems`, which hasn't been implemented yet. +// set SetOfRangeByte { +// member: RangeByte +// } + +list ListOfRangeByte { + member: RangeByte +} + list ListOfEnumString { member: EnumString } From b7c03539ad70fdf406c17afad6bc4f1460a5b642 Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:13:56 +0000 Subject: [PATCH 3/7] Implement @range for long and byte shapes. --- .../smithy/ConstrainedShapeSymbolProvider.kt | 5 +++- .../ConstraintViolationSymbolProvider.kt | 4 ++- .../rust/codegen/server/smithy/Constraints.kt | 6 ++-- .../server/smithy/ServerCodegenVisitor.kt | 22 +++++++++++++++ .../smithy/ValidateUnsupportedConstraints.kt | 6 ++-- ...eforeSerializingMemberJsonCustomization.kt | 8 ++++-- ...rator.kt => ConstrainedNumberGenerator.kt} | 26 +++++++++++++++++ .../http/ServerResponseBindingGenerator.kt | 4 ++- ...hapeReachableFromOperationInputTagTrait.kt | 4 ++- ...ShapesReachableFromOperationInputTagger.kt | 6 +++- .../ConstrainedShapeSymbolProviderTest.kt | 10 +++++++ ...ateUnsupportedConstraintsAreNotUsedTest.kt | 28 ------------------- .../ConstrainedNumberGeneratorTest.kt | 5 +++- 13 files changed, 94 insertions(+), 40 deletions(-) rename codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/{ConstrainedIntegerGenerator.kt => ConstrainedNumberGenerator.kt} (93%) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index 64a45b389a..c58df709a6 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -8,8 +8,10 @@ package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model import software.amazon.smithy.model.knowledge.NullableIndex +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.ServiceShape @@ -98,10 +100,11 @@ class ConstrainedShapeSymbolProvider( } } - is StringShape, is IntegerShape, is ShortShape -> { + is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape -> { if (shape.isDirectlyConstrained(base)) { val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() + symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() } else { base.toSymbol(shape) } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt index 2a0fc92009..d78424ec75 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstraintViolationSymbolProvider.kt @@ -7,8 +7,10 @@ package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.codegen.core.Symbol import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape @@ -115,7 +117,7 @@ class ConstraintViolationSymbolProvider( .build() } - is StringShape, is IntegerShape, is ShortShape -> { + is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape -> { val module = shape.shapeModule() val rustType = RustType.Opaque(constraintViolationName, module.fullyQualifiedPath()) Symbol.builder() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt index aeffa2345c..c90e28384f 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/Constraints.kt @@ -8,8 +8,10 @@ package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.codegen.core.SymbolProvider import software.amazon.smithy.model.Model import software.amazon.smithy.model.neighbor.Walker +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.Shape @@ -73,7 +75,7 @@ fun Shape.isDirectlyConstrained(symbolProvider: SymbolProvider): Boolean = when is MapShape -> this.hasTrait() is StringShape -> this.hasTrait() || supportedStringConstraintTraits.any { this.hasTrait(it) } - is IntegerShape, is ShortShape -> this.hasTrait() + is IntegerShape, is ShortShape, is LongShape, is ByteShape -> this.hasTrait() else -> false } @@ -99,7 +101,7 @@ fun MemberShape.targetCanReachConstrainedShape(model: Model, symbolProvider: Sym fun Shape.hasPublicConstrainedWrapperTupleType(model: Model, publicConstrainedTypes: Boolean): Boolean = when (this) { is MapShape -> publicConstrainedTypes && this.hasTrait() is StringShape -> !this.hasTrait() && (publicConstrainedTypes && supportedStringConstraintTraits.any(this::hasTrait)) - is IntegerShape, is ShortShape -> publicConstrainedTypes && this.hasTrait() + is IntegerShape, is ShortShape, is LongShape, is ByteShape -> publicConstrainedTypes && this.hasTrait() is MemberShape -> model.expectShape(this.target).hasPublicConstrainedWrapperTupleType(model, publicConstrainedTypes) else -> false } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index 5207cd3aa3..cf7dfd856d 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -10,9 +10,11 @@ import software.amazon.smithy.codegen.core.CodegenException import software.amazon.smithy.model.Model import software.amazon.smithy.model.knowledge.NullableIndex import software.amazon.smithy.model.neighbor.Walker +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.ListShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.SetShape @@ -44,7 +46,9 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.RecursiveSha import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.runCommand +import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedByteGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedIntegerGenerator +import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedLongGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedMapGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedShortGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedStringGenerator @@ -372,6 +376,24 @@ open class ServerCodegenVisitor( } } + override fun longShape(shape: LongShape) { + if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { + logger.info("[rust-server-codegen] Generating a constrained long $shape") + rustCrate.withModule(ModelsModule) { + ConstrainedLongGenerator(codegenContext, this, shape).render() + } + } + } + + override fun byteShape(shape: ByteShape) { + if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { + logger.info("[rust-server-codegen] Generating a constrained byte $shape") + rustCrate.withModule(ModelsModule) { + ConstrainedByteGenerator(codegenContext, this, shape).render() + } + } + } + protected fun stringShape( shape: StringShape, enumShapeGeneratorFactory: (codegenContext: ServerCodegenContext, writer: RustWriter, shape: StringShape) -> ServerEnumGenerator, diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt index aecde3538d..8155b1d8ab 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraints.kt @@ -8,9 +8,11 @@ package software.amazon.smithy.rust.codegen.server.smithy import software.amazon.smithy.model.Model import software.amazon.smithy.model.neighbor.Walker import software.amazon.smithy.model.shapes.BlobShape +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.EnumShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MemberShape import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.ServiceShape @@ -241,12 +243,12 @@ fun validateUnsupportedConstraints( .map { UnsupportedLengthTraitOnCollectionOrOnBlobShape(it, it.expectTrait()) } .toSet() - // 5. Range trait used on a non-integer shape. It has not been implemented yet. + // 5. Range trait used on unsupported shapes. // TODO(https://github.com/awslabs/smithy-rs/issues/1401) val unsupportedRangeTraitOnShapeSet = walker .walkShapes(service) .asSequence() - .filterNot { it is IntegerShape || it is ShortShape } + .filterNot { it is IntegerShape || it is ShortShape || it is LongShape || it is ByteShape } .filterMapShapesToTraits(setOf(RangeTrait::class.java)) .map { (shape, rangeTrait) -> UnsupportedRangeTraitOnShape(shape, rangeTrait as RangeTrait) } .toSet() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/BeforeSerializingMemberJsonCustomization.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/BeforeSerializingMemberJsonCustomization.kt index 4d3936496b..dde7dbbafe 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/BeforeSerializingMemberJsonCustomization.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/customizations/BeforeSerializingMemberJsonCustomization.kt @@ -5,7 +5,9 @@ package software.amazon.smithy.rust.codegen.server.smithy.customizations +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.writable @@ -19,7 +21,8 @@ import software.amazon.smithy.rust.codegen.server.smithy.workingWithPublicConstr * A customization to, just before we serialize a _constrained_ shape in a JSON serializer, unwrap the wrapper * newtype and take a shared reference to the actual unconstrained value within it. */ -class BeforeSerializingMemberJsonCustomization(private val codegenContext: ServerCodegenContext) : JsonSerializerCustomization() { +class BeforeSerializingMemberJsonCustomization(private val codegenContext: ServerCodegenContext) : + JsonSerializerCustomization() { override fun section(section: JsonSerializerSection): Writable = when (section) { is JsonSerializerSection.BeforeSerializingNonNullMember -> writable { if (workingWithPublicConstrainedWrapperTupleType( @@ -28,12 +31,13 @@ class BeforeSerializingMemberJsonCustomization(private val codegenContext: Serve codegenContext.settings.codegenConfig.publicConstrainedTypes, ) ) { - if (section.shape is IntegerShape || section.shape is ShortShape) { + if (section.shape is IntegerShape || section.shape is ShortShape || section.shape is LongShape || section.shape is ByteShape) { section.context.valueExpression = ValueExpression.Reference("&${section.context.valueExpression.name}.0") } } } + else -> emptySection } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedIntegerGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt similarity index 93% rename from codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedIntegerGenerator.kt rename to codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt index 2cb14edf7f..96142c995a 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedIntegerGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt @@ -6,7 +6,9 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators import software.amazon.smithy.codegen.core.Symbol +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.NumberShape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.traits.RangeTrait @@ -57,6 +59,30 @@ class ConstrainedShortGenerator( } } +class ConstrainedLongGenerator( + val codegenContext: ServerCodegenContext, + val writer: RustWriter, + val shape: LongShape, +) { + val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(64)) + + fun render() { + inner.render() + } +} + +class ConstrainedByteGenerator( + val codegenContext: ServerCodegenContext, + val writer: RustWriter, + val shape: ByteShape, +) { + val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(8)) + + fun render() { + inner.render() + } +} + /** * [ConstrainedNumberGenerator] generates a wrapper newtype holding a constrained number primitive. * This type can be built from unconstrained values, yielding a `ConstraintViolation` when the input does not satisfy diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt index 1503096027..ae564c9c86 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/http/ServerResponseBindingGenerator.kt @@ -6,7 +6,9 @@ package software.amazon.smithy.rust.codegen.server.smithy.generators.http import software.amazon.smithy.codegen.core.Symbol +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.OperationShape import software.amazon.smithy.model.shapes.Shape import software.amazon.smithy.model.shapes.ShortShape @@ -92,7 +94,7 @@ class ServerResponseBeforeRenderingHeadersHttpBindingCustomization(val codegenCo codegenContext.settings.codegenConfig.publicConstrainedTypes, ) ) { - if (section.context.shape is IntegerShape || section.context.shape is ShortShape) { + if (section.context.shape is IntegerShape || section.context.shape is ShortShape || section.context.shape is LongShape || section.context.shape is ByteShape) { section.context.valueExpression = ValueExpression.Reference("&${section.context.valueExpression.name.removePrefix("&")}.0") } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/ShapeReachableFromOperationInputTagTrait.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/ShapeReachableFromOperationInputTagTrait.kt index f0cfccb7d7..36258b8e37 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/ShapeReachableFromOperationInputTagTrait.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/traits/ShapeReachableFromOperationInputTagTrait.kt @@ -6,9 +6,11 @@ package software.amazon.smithy.rust.codegen.server.smithy.traits import software.amazon.smithy.model.node.Node +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.CollectionShape import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.ListShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.NumberShape import software.amazon.smithy.model.shapes.Shape @@ -33,7 +35,7 @@ class ShapeReachableFromOperationInputTagTrait : AnnotationTrait(ID, Node.object } private fun isShapeReachableFromOperationInput(shape: Shape) = when (shape) { - is StructureShape, is UnionShape, is MapShape, is ListShape, is StringShape, is IntegerShape, is ShortShape -> { + is StructureShape, is UnionShape, is MapShape, is ListShape, is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape -> { shape.hasTrait() } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ShapesReachableFromOperationInputTagger.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ShapesReachableFromOperationInputTagger.kt index 3a16481935..66d532ce62 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ShapesReachableFromOperationInputTagger.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/transformers/ShapesReachableFromOperationInputTagger.kt @@ -7,8 +7,10 @@ package software.amazon.smithy.rust.codegen.server.smithy.transformers import software.amazon.smithy.model.Model import software.amazon.smithy.model.neighbor.Walker +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape import software.amazon.smithy.model.shapes.ListShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.model.shapes.StringShape @@ -52,7 +54,7 @@ object ShapesReachableFromOperationInputTagger { return ModelTransformer.create().mapShapes(model) { shape -> when (shape) { - is StructureShape, is UnionShape, is ListShape, is MapShape, is StringShape, is IntegerShape, is ShortShape -> { + is StructureShape, is UnionShape, is ListShape, is MapShape, is StringShape, is IntegerShape, is ShortShape, is LongShape, is ByteShape -> { if (shapesReachableFromOperationInputs.contains(shape)) { val builder = when (shape) { is StructureShape -> shape.toBuilder() @@ -62,6 +64,8 @@ object ShapesReachableFromOperationInputTagger { is StringShape -> shape.toBuilder() is IntegerShape -> shape.toBuilder() is ShortShape -> shape.toBuilder() + is LongShape -> shape.toBuilder() + is ByteShape -> shape.toBuilder() else -> UNREACHABLE("the `when` is exhaustive") } builder.addTrait(ShapeReachableFromOperationInputTagTrait()).build() diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt index 90501ac178..2a98ccd144 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProviderTest.kt @@ -10,7 +10,9 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.MapShape import software.amazon.smithy.model.shapes.ServiceShape import software.amazon.smithy.model.shapes.Shape @@ -51,6 +53,12 @@ const val baseModelString = @range(min: -2, max: 10) short ConstrainedShort + @range(min: -2, max: 1000) + long ConstrainedLong + + @range(min: -2, max: 10) + byte ConstrainedByte + @range(min: 10, max: 29) integer ConstrainedInteger @@ -85,6 +93,8 @@ class ConstrainedShapeSymbolProviderTest { Stream.of( Arguments.of("ConstrainedInteger", { s: Shape -> s is IntegerShape }), Arguments.of("ConstrainedShort", { s: Shape -> s is ShortShape }), + Arguments.of("ConstrainedLong", { s: Shape -> s is LongShape }), + Arguments.of("ConstrainedByte", { s: Shape -> s is ByteShape }), Arguments.of("ConstrainedString", { s: Shape -> s is StringShape }), Arguments.of("ConstrainedMap", { s: Shape -> s is MapShape }), ) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt index 5d0842681d..e75eaacb0b 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ValidateUnsupportedConstraintsAreNotUsedTest.kt @@ -176,34 +176,6 @@ internal class ValidateUnsupportedConstraintsAreNotUsedTest { validationResult.messages.forSome { it.message shouldContain "The blob shape `test#LengthBlob` has the constraint trait `smithy.api#length` attached" } } - @Test - fun `it should detect when the range trait is used on a shape we do not support`() { - val model = - """ - $baseModel - - structure TestInputOutput { - rangeByte: RangeByte - rangeShort: RangeShort - rangeLong: RangeLong - } - - @range(min: 1) - byte RangeByte - - @range(min: 1) - long RangeLong - - @range(min: 1) - short RangeShort - """.asSmithyModel() - val validationResult = validateModel(model) - - validationResult.messages shouldHaveSize 2 - validationResult.messages[0].message shouldContain "The long shape `test#RangeLong` has the constraint trait `smithy.api#range` attached" - validationResult.messages[1].message shouldContain "The byte shape `test#RangeByte` has the constraint trait `smithy.api#range` attached" - } - @Test fun `it should detect when the unique items trait is used`() { val model = diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 4289c9f338..dd28fe6625 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -58,7 +58,8 @@ class ConstrainedNumberGeneratorTest { } override fun provideArguments(context: ExtensionContext?): Stream = - listOf("integer", "short").map { type -> testCases(type) }.flatten().map { Arguments.of(it) }.stream() + listOf("integer", "short", "long", "byte").map { type -> testCases(type) }.flatten() + .map { Arguments.of(it) }.stream() } @ParameterizedTest @@ -116,6 +117,8 @@ class ConstrainedNumberGeneratorTest { listOf( Triple("integer", "ConstrainedInteger", "i32"), Triple("short", "ConstrainedShort", "i16"), + Triple("long", "ConstrainedLong", "i64"), + Triple("byte", "ConstrainedByte", "i8"), ).map { Arguments.of(it) }.stream() } From 1f885d88fe4073c9285c04fde1f6062821877e79 Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:15:27 +0000 Subject: [PATCH 4/7] Update CHANGELOG --- CHANGELOG.next.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index ce040e782a..697e4eac6f 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -242,15 +242,17 @@ message = """ * The `length` trait on `string` shapes. * The `length` trait on `map` shapes. -* The `range` trait on `integer` shapes. +* The `range` trait on `byte` shapes. * The `range` trait on `short` shapes. +* The `range` trait on `integer` shapes. +* The `range` trait on `long` shapes. * The `pattern` trait on `string` shapes. Upon receiving a request that violates the modeled constraints, the server SDK will reject it with a message indicating why. Unsupported (constraint trait, target shape) combinations will now fail at code generation time, whereas previously they were just ignored. This is a breaking change to raise awareness in service owners of their server SDKs behaving differently than what was modeled. To continue generating a server SDK with unsupported constraint traits, set `codegenConfig.ignoreUnsupportedConstraints` to `true` in your `smithy-build.json`. """ -references = ["smithy-rs#1199", "smithy-rs#1342", "smithy-rs#1401", "smithy-rs#2005", "smithy-rs#1998", "smithy-rs#2034"] +references = ["smithy-rs#1199", "smithy-rs#1342", "smithy-rs#1401", "smithy-rs#2005", "smithy-rs#1998", "smithy-rs#2034", "smithy-rs#2036"] meta = { "breaking" = true, "tada" = true, "bug" = false, "target" = "server" } author = "david-perez" From bd2aa02136d5b15d454456942b771fcad93019ba Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 15:30:32 +0000 Subject: [PATCH 5/7] Fix unit tests. --- .../smithy/generators/ConstrainedNumberGeneratorTest.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index dd28fe6625..475da785c0 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -12,7 +12,9 @@ import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.ArgumentsProvider import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model +import software.amazon.smithy.model.shapes.ByteShape import software.amazon.smithy.model.shapes.IntegerShape +import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.NumberShape import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter @@ -76,6 +78,8 @@ class ConstrainedNumberGeneratorTest { when (shape) { is IntegerShape -> ConstrainedIntegerGenerator(codegenContext, this, shape).render() is ShortShape -> ConstrainedShortGenerator(codegenContext, this, shape).render() + is ByteShape -> ConstrainedByteGenerator(codegenContext, this, shape).render() + is LongShape -> ConstrainedLongGenerator(codegenContext, this, shape).render() } unitTest( @@ -141,6 +145,8 @@ class ConstrainedNumberGeneratorTest { when (constrainedShape) { is IntegerShape -> ConstrainedIntegerGenerator(codegenContext, writer, constrainedShape).render() is ShortShape -> ConstrainedShortGenerator(codegenContext, writer, constrainedShape).render() + is ByteShape -> ConstrainedByteGenerator(codegenContext, writer, constrainedShape).render() + is LongShape -> ConstrainedLongGenerator(codegenContext, writer, constrainedShape).render() } // Check that the wrapped type is `pub(crate)`. From ee988515c4afefe8b6b8a7cadc371f7dbd6906c6 Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 16:09:55 +0000 Subject: [PATCH 6/7] Address comments --- .../codegen/server/smithy/ConstrainedShapeSymbolProvider.kt | 1 - .../smithy/generators/ConstrainedNumberGeneratorTest.kt | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt index c58df709a6..c614e03007 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ConstrainedShapeSymbolProvider.kt @@ -104,7 +104,6 @@ class ConstrainedShapeSymbolProvider( if (shape.isDirectlyConstrained(base)) { val rustType = RustType.Opaque(shape.contextName(serviceShape).toPascalCase()) symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() - symbolBuilder(shape, rustType).locatedIn(ModelsModule).build() } else { base.toSymbol(shape) } diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index 475da785c0..e12caaae46 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -119,10 +119,10 @@ class ConstrainedNumberGeneratorTest { class NoStructuralConstructorTestProvider : ArgumentsProvider { override fun provideArguments(context: ExtensionContext?): Stream = listOf( - Triple("integer", "ConstrainedInteger", "i32"), + Triple("byte", "ConstrainedByte", "i8"), Triple("short", "ConstrainedShort", "i16"), + Triple("integer", "ConstrainedInteger", "i32"), Triple("long", "ConstrainedLong", "i64"), - Triple("byte", "ConstrainedByte", "i8"), ).map { Arguments.of(it) }.stream() } From 21a3bec4e0fad0db09f80422d066423e2166135b Mon Sep 17 00:00:00 2001 From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> Date: Tue, 29 Nov 2022 16:16:16 +0000 Subject: [PATCH 7/7] Dry up further. --- .../server/smithy/ServerCodegenVisitor.kt | 13 ++-- .../generators/ConstrainedNumberGenerator.kt | 59 ++++--------------- .../ConstrainedNumberGeneratorTest.kt | 19 +----- 3 files changed, 17 insertions(+), 74 deletions(-) diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt index cf7dfd856d..23d3e6f0f0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/ServerCodegenVisitor.kt @@ -46,11 +46,8 @@ import software.amazon.smithy.rust.codegen.core.smithy.transformers.RecursiveSha import software.amazon.smithy.rust.codegen.core.util.CommandFailed import software.amazon.smithy.rust.codegen.core.util.hasTrait import software.amazon.smithy.rust.codegen.core.util.runCommand -import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedByteGenerator -import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedIntegerGenerator -import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedLongGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedMapGenerator -import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedShortGenerator +import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedNumberGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedStringGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.ConstrainedTraitForEnumGenerator import software.amazon.smithy.rust.codegen.server.smithy.generators.MapConstraintViolationGenerator @@ -362,7 +359,7 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained integer $shape") rustCrate.withModule(ModelsModule) { - ConstrainedIntegerGenerator(codegenContext, this, shape).render() + ConstrainedNumberGenerator(codegenContext, this, shape).render() } } } @@ -371,7 +368,7 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained short $shape") rustCrate.withModule(ModelsModule) { - ConstrainedShortGenerator(codegenContext, this, shape).render() + ConstrainedNumberGenerator(codegenContext, this, shape).render() } } } @@ -380,7 +377,7 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained long $shape") rustCrate.withModule(ModelsModule) { - ConstrainedLongGenerator(codegenContext, this, shape).render() + ConstrainedNumberGenerator(codegenContext, this, shape).render() } } } @@ -389,7 +386,7 @@ open class ServerCodegenVisitor( if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { logger.info("[rust-server-codegen] Generating a constrained byte $shape") rustCrate.withModule(ModelsModule) { - ConstrainedByteGenerator(codegenContext, this, shape).render() + ConstrainedNumberGenerator(codegenContext, this, shape).render() } } } diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt index 96142c995a..e393083ec0 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGenerator.kt @@ -28,6 +28,7 @@ import software.amazon.smithy.rust.codegen.core.rustlang.rustTemplate import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.makeMaybeConstrained import software.amazon.smithy.rust.codegen.core.smithy.module +import software.amazon.smithy.rust.codegen.core.util.UNREACHABLE import software.amazon.smithy.rust.codegen.core.util.expectTrait import software.amazon.smithy.rust.codegen.core.util.redactIfNecessary import software.amazon.smithy.rust.codegen.server.smithy.PubCrateConstraintViolationSymbolProvider @@ -35,54 +36,6 @@ import software.amazon.smithy.rust.codegen.server.smithy.ServerCodegenContext import software.amazon.smithy.rust.codegen.server.smithy.traits.isReachableFromOperationInput import software.amazon.smithy.rust.codegen.server.smithy.validationErrorMessage -class ConstrainedIntegerGenerator( - val codegenContext: ServerCodegenContext, - val writer: RustWriter, - val shape: IntegerShape, -) { - val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(32)) - - fun render() { - inner.render() - } -} - -class ConstrainedShortGenerator( - val codegenContext: ServerCodegenContext, - val writer: RustWriter, - val shape: ShortShape, -) { - val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(16)) - - fun render() { - inner.render() - } -} - -class ConstrainedLongGenerator( - val codegenContext: ServerCodegenContext, - val writer: RustWriter, - val shape: LongShape, -) { - val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(64)) - - fun render() { - inner.render() - } -} - -class ConstrainedByteGenerator( - val codegenContext: ServerCodegenContext, - val writer: RustWriter, - val shape: ByteShape, -) { - val inner = ConstrainedNumberGenerator(codegenContext, writer, shape, RustType.Integer(8)) - - fun render() { - inner.render() - } -} - /** * [ConstrainedNumberGenerator] generates a wrapper newtype holding a constrained number primitive. * This type can be built from unconstrained values, yielding a `ConstraintViolation` when the input does not satisfy @@ -92,11 +45,19 @@ class ConstrainedNumberGenerator( val codegenContext: ServerCodegenContext, val writer: RustWriter, val shape: NumberShape, - private val unconstrainedType: RustType, ) { val model = codegenContext.model val constrainedShapeSymbolProvider = codegenContext.constrainedShapeSymbolProvider val publicConstrainedTypes = codegenContext.settings.codegenConfig.publicConstrainedTypes + + private val unconstrainedType = when (shape) { + is ByteShape -> RustType.Integer(8) + is ShortShape -> RustType.Integer(16) + is IntegerShape -> RustType.Integer(32) + is LongShape -> RustType.Integer(64) + else -> UNREACHABLE("Trying to generate a constrained number for an unsupported Smithy number shape") + } + private val constraintViolationSymbolProvider = with(codegenContext.constraintViolationSymbolProvider) { if (publicConstrainedTypes) { diff --git a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt index e12caaae46..681d0fffe3 100644 --- a/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt +++ b/codegen-server/src/test/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ConstrainedNumberGeneratorTest.kt @@ -12,11 +12,7 @@ import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.ArgumentsProvider import org.junit.jupiter.params.provider.ArgumentsSource import software.amazon.smithy.model.Model -import software.amazon.smithy.model.shapes.ByteShape -import software.amazon.smithy.model.shapes.IntegerShape -import software.amazon.smithy.model.shapes.LongShape import software.amazon.smithy.model.shapes.NumberShape -import software.amazon.smithy.model.shapes.ShortShape import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.smithy.ModelsModule import software.amazon.smithy.rust.codegen.core.testutil.TestWorkspace @@ -75,12 +71,7 @@ class ConstrainedNumberGeneratorTest { val project = TestWorkspace.testProject(symbolProvider) project.withModule(ModelsModule) { - when (shape) { - is IntegerShape -> ConstrainedIntegerGenerator(codegenContext, this, shape).render() - is ShortShape -> ConstrainedShortGenerator(codegenContext, this, shape).render() - is ByteShape -> ConstrainedByteGenerator(codegenContext, this, shape).render() - is LongShape -> ConstrainedLongGenerator(codegenContext, this, shape).render() - } + ConstrainedNumberGenerator(codegenContext, this, shape).render() unitTest( name = "try_from_success", @@ -141,13 +132,7 @@ class ConstrainedNumberGeneratorTest { val codegenContext = serverTestCodegenContext(model) val writer = RustWriter.forModule(ModelsModule.name) - - when (constrainedShape) { - is IntegerShape -> ConstrainedIntegerGenerator(codegenContext, writer, constrainedShape).render() - is ShortShape -> ConstrainedShortGenerator(codegenContext, writer, constrainedShape).render() - is ByteShape -> ConstrainedByteGenerator(codegenContext, writer, constrainedShape).render() - is LongShape -> ConstrainedLongGenerator(codegenContext, writer, constrainedShape).render() - } + ConstrainedNumberGenerator(codegenContext, writer, constrainedShape).render() // Check that the wrapped type is `pub(crate)`. writer.toString() shouldContain "pub struct $shapeName(pub(crate) $rustType);"