From 4c779651263304cc58b1317baacf54ba9c61d138 Mon Sep 17 00:00:00 2001
From: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com>
Date: Tue, 29 Nov 2022 17:04:54 +0000
Subject: [PATCH] Implement @range on long and byte shapes (#2036)

* Group all override-related test cases together.

* Add @range examples for both byte and long in constraints.smithy.

* Implement @range for long and byte shapes.

* Update CHANGELOG

* Fix unit tests.

* Address comments

* Dry up further.
---
 CHANGELOG.next.toml                           |   6 +-
 .../common-test-models/constraints.smithy     | 132 +++++++++++++++++-
 .../smithy/ConstrainedShapeSymbolProvider.kt  |   4 +-
 .../ConstraintViolationSymbolProvider.kt      |   4 +-
 .../rust/codegen/server/smithy/Constraints.kt |   6 +-
 .../server/smithy/ServerCodegenVisitor.kt     |  27 +++-
 .../smithy/ValidateUnsupportedConstraints.kt  |   6 +-
 ...eforeSerializingMemberJsonCustomization.kt |   8 +-
 ...rator.kt => ConstrainedNumberGenerator.kt} |  37 ++---
 .../http/ServerResponseBindingGenerator.kt    |   4 +-
 .../protocol/ServerProtocolTestGenerator.kt   | 111 ++++++++-------
 ...hapeReachableFromOperationInputTagTrait.kt |   4 +-
 ...ShapesReachableFromOperationInputTagger.kt |   6 +-
 .../ConstrainedShapeSymbolProviderTest.kt     |  10 ++
 ...ateUnsupportedConstraintsAreNotUsedTest.kt |  28 ----
 .../ConstrainedNumberGeneratorTest.kt         |  20 +--
 16 files changed, 280 insertions(+), 133 deletions(-)
 rename codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/{ConstrainedIntegerGenerator.kt => ConstrainedNumberGenerator.kt} (93%)

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<LengthTrait>()
     is StringShape -> this.hasTrait<EnumTrait>() || supportedStringConstraintTraits.any { this.hasTrait(it) }
-    is IntegerShape, is ShortShape -> this.hasTrait<RangeTrait>()
+    is IntegerShape, is ShortShape, is LongShape, is ByteShape -> this.hasTrait<RangeTrait>()
     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<LengthTrait>()
     is StringShape -> !this.hasTrait<EnumTrait>() && (publicConstrainedTypes && supportedStringConstraintTraits.any(this::hasTrait))
-    is IntegerShape, is ShortShape -> publicConstrainedTypes && this.hasTrait<RangeTrait>()
+    is IntegerShape, is ShortShape, is LongShape, is ByteShape -> publicConstrainedTypes && this.hasTrait<RangeTrait>()
     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<ShapeReachableFromOperationInputTagTrait>()
     }
 
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<out Arguments> =
-            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<out Arguments> =
             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);"