diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 01ee71b03e..aa9ae8ab73 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" 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 } 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..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 @@ -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,7 +100,7 @@ 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() 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..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 @@ -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,9 +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.ConstrainedIntegerGenerator 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 @@ -358,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() } } } @@ -367,7 +368,25 @@ 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() + } + } + } + + override fun longShape(shape: LongShape) { + if (shape.isDirectlyConstrained(codegenContext.symbolProvider)) { + logger.info("[rust-server-codegen] Generating a constrained long $shape") + rustCrate.withModule(ModelsModule) { + ConstrainedNumberGenerator(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) { + ConstrainedNumberGenerator(codegenContext, this, shape).render() } } } 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..e393083ec0 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 @@ -26,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 @@ -33,30 +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() - } -} - /** * [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 @@ -66,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/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/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), 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..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,9 +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.IntegerShape 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 @@ -58,7 +56,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 @@ -72,10 +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() - } + ConstrainedNumberGenerator(codegenContext, this, shape).render() unitTest( name = "try_from_success", @@ -114,8 +110,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"), ).map { Arguments.of(it) }.stream() } @@ -134,11 +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() - } + ConstrainedNumberGenerator(codegenContext, writer, constrainedShape).render() // Check that the wrapped type is `pub(crate)`. writer.toString() shouldContain "pub struct $shapeName(pub(crate) $rustType);"