Skip to content

Commit eb48261

Browse files
authored
codegen-serde: traverse operations of resources (#3882)
The current implementation doesn't traverse a resource's operations if the serialization root is a service shape; the added test fails without this fix. ---- _By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice._
1 parent ef07c88 commit eb48261

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

codegen-serde/src/main/kotlin/software/amazon/smithy/rust/codegen/serde/SerializeImplGenerator.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package software.amazon.smithy.rust.codegen.serde
77

88
import software.amazon.smithy.codegen.core.Symbol
9+
import software.amazon.smithy.model.knowledge.TopDownIndex
910
import software.amazon.smithy.model.shapes.BlobShape
1011
import software.amazon.smithy.model.shapes.BooleanShape
1112
import software.amazon.smithy.model.shapes.CollectionShape
@@ -61,6 +62,7 @@ import software.amazon.smithy.rust.codegen.server.smithy.hasConstraintTrait
6162

6263
class SerializeImplGenerator(private val codegenContext: CodegenContext) {
6364
private val model = codegenContext.model
65+
private val topIndex = TopDownIndex.of(model)
6466

6567
fun generateRootSerializerForShape(shape: Shape): Writable = serializerFn(shape, null)
6668

@@ -78,7 +80,9 @@ class SerializeImplGenerator(private val codegenContext: CodegenContext) {
7880
applyTo: Writable?,
7981
): Writable {
8082
if (shape is ServiceShape) {
81-
return shape.operations.map { serializerFn(model.expectShape(it), null) }.join("\n")
83+
return topIndex.getContainedOperations(shape).map {
84+
serializerFn(it, null)
85+
}.join("\n")
8286
} else if (shape is OperationShape) {
8387
if (shape.isEventStream(model)) {
8488
// Don't generate serializers for event streams

codegen-serde/src/test/kotlin/software/amazon/smithy/rust/codegen/serde/SerdeDecoratorTest.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,58 @@ class SerdeDecoratorTest {
179179
structure NotSerde {}
180180
""".asSmithyModel(smithyVersion = "2")
181181

182+
@Test
183+
fun `decorator should traverse resources`() {
184+
val model =
185+
"""
186+
namespace com.example
187+
use smithy.rust#serde
188+
use aws.protocols#awsJson1_0
189+
190+
@awsJson1_0
191+
@serde
192+
service MyResourceService {
193+
resources: [MyResource]
194+
}
195+
196+
resource MyResource {
197+
read: ReadMyResource
198+
}
199+
200+
@readonly
201+
operation ReadMyResource {
202+
input := { }
203+
}
204+
""".asSmithyModel(smithyVersion = "2")
205+
206+
val params =
207+
IntegrationTestParams(cargoCommand = "cargo test --all-features", service = "com.example#MyResourceService")
208+
serverIntegrationTest(model, params = params) { ctx, crate ->
209+
val codegenScope =
210+
arrayOf(
211+
"crate" to RustType.Opaque(ctx.moduleUseName()),
212+
"serde_json" to CargoDependency("serde_json", CratesIo("1")).toDevDependency().toType(),
213+
// we need the derive feature
214+
"serde" to CargoDependency.Serde.toDevDependency().toType(),
215+
)
216+
217+
crate.integrationTest("test_serde") {
218+
unitTest("input_serialized") {
219+
rustTemplate(
220+
"""
221+
use #{crate}::input::ReadMyResourceInput;
222+
use #{crate}::serde::*;
223+
let input = ReadMyResourceInput { };
224+
let settings = SerializationSettings::default();
225+
let _serialized = #{serde_json}::to_string(&input.serialize_ref(&settings)).expect("failed to serialize");
226+
""",
227+
*codegenScope,
228+
)
229+
}
230+
}
231+
}
232+
}
233+
182234
@Test
183235
fun generateSerializersThatWorkServer() {
184236
serverIntegrationTest(simpleModel, params = params) { ctx, crate ->

0 commit comments

Comments
 (0)