@@ -29,6 +29,7 @@ import software.amazon.smithy.swift.codegen.integration.serde.getDefaultValueOfS
2929import software.amazon.smithy.swift.codegen.model.hasTrait
3030import software.amazon.smithy.swift.codegen.model.isBoxed
3131import software.amazon.smithy.swift.codegen.removeSurroundingBackticks
32+ import software.amazon.smithy.swift.codegen.utils.toLowerCamelCase
3233
3334/*
3435Includes functions to help render conformance to Encodable protocol for shapes
@@ -86,28 +87,14 @@ abstract class MemberShapeEncodeGenerator(
8687 renderEncodeList(ctx, memberName, topLevelContainerName, targetShape, level)
8788 } else {
8889 writer.write(" var \$ L = $containerName .nestedUnkeyedContainer()" , topLevelContainerName)
89- val isSparse = targetShape.hasTrait<SparseTrait >()
90- if (isSparse) {
91- writer.openBlock(" if let \$ L = \$ L {" , " }" , memberName, memberName) {
92- renderEncodeList(ctx, memberName, topLevelContainerName, targetShape, level)
93- }
94- } else {
95- renderEncodeList(ctx, memberName, topLevelContainerName, targetShape, level)
96- }
90+ renderEncodeList(ctx, memberName, topLevelContainerName, targetShape, level)
9791 }
9892 }
9993 // this only gets called in a recursive loop where there is a map nested deeply inside a list
10094 is MapShape -> {
10195 val topLevelContainerName = " ${memberName} Container"
10296 writer.write(" var \$ L = $containerName .nestedContainer(keyedBy: \$ N.self)" , topLevelContainerName, ClientRuntimeTypes .Serde .Key )
103- val isSparse = targetShape.hasTrait<SparseTrait >()
104- if (isSparse) {
105- writer.openBlock(" if let \$ L = \$ L {" , " }" , memberName, memberName) {
106- renderEncodeMap(ctx, memberName, topLevelContainerName, targetShape, level)
107- }
108- } else {
109- renderEncodeMap(ctx, memberName, topLevelContainerName, targetShape, level)
110- }
97+ renderEncodeMap(ctx, memberName, topLevelContainerName, targetShape, level)
11198 }
11299 else -> {
113100 renderSimpleShape(targetShape, memberName, containerName, null , false )
@@ -151,24 +138,22 @@ abstract class MemberShapeEncodeGenerator(
151138 ctx : ProtocolGenerator .GenerationContext ,
152139 collectionName : String ,
153140 topLevelContainerName : String ,
154- targetShape : Shape ,
141+ listShape : CollectionShape ,
155142 level : Int = 0
156143 ) {
144+ val listIsSparse = listShape.hasTrait<SparseTrait >()
145+ val targetShape = ctx.model.expectShape(listShape.member.target)
157146 val iteratorName = " ${targetShape.id.name.lowercase()}$level "
158147 writer.openBlock(" for $iteratorName in $collectionName {" , " }" ) {
159- when (targetShape ) {
160- is CollectionShape -> {
161- val nestedTarget = ctx.model.expectShape(targetShape.member.target )
162- renderEncodeListMember(nestedTarget, iteratorName, topLevelContainerName, level + 1 )
148+ if (listIsSparse ) {
149+ writer.openBlock( " guard let \$ L = \$ L else { " , " } " , iteratorName, iteratorName) {
150+ writer.write( " try \$ L.encodeNil() " , topLevelContainerName )
151+ writer.write( " continue " )
163152 }
164- is MapShape -> {
165- val nestedTarget = ctx.model.expectShape(targetShape.value.target)
166- renderEncodeMapMember(
167- nestedTarget,
168- " ${ClientRuntimeTypes .Serde .Key } (stringValue: $dictKey )" ,
169- topLevelContainerName,
170- level + 1
171- )
153+ }
154+ when (targetShape) {
155+ is CollectionShape , is MapShape -> {
156+ renderEncodeListMember(targetShape, iteratorName, topLevelContainerName, level + 1 )
172157 }
173158 else -> {
174159 val isBoxed = ctx.symbolProvider.toSymbol(targetShape).isBoxed() && targetShape.hasTrait<SparseTrait >()
@@ -186,31 +171,31 @@ abstract class MemberShapeEncodeGenerator(
186171
187172 // Render encoding of a member of Map type
188173 fun renderEncodeMapMember (targetShape : Shape , memberName : String , containerName : String , level : Int = 0) {
174+ val keyName = if (level == 0 ) " .$memberName " else " ${ClientRuntimeTypes .Serde .Key } (stringValue: $dictKey${level - 1 } )"
189175 when (targetShape) {
190176 is CollectionShape -> {
191177 val topLevelContainerName = " ${memberName} Container"
192- writer.write(" var \$ L = $containerName .nestedUnkeyedContainer(forKey: \$ N( $dictKey${level - 1 } )) " , topLevelContainerName, ClientRuntimeTypes . Serde . Key )
178+ writer.write(" var \$ L = $containerName .nestedUnkeyedContainer(forKey: \$ L) " , topLevelContainerName, keyName )
193179 renderEncodeList(ctx, memberName, topLevelContainerName, targetShape, level)
194180 }
195181 is MapShape -> {
196182 val topLevelContainerName = " ${memberName} Container"
197183 writer.write(
198- " var \$ L = $containerName .nestedContainer(keyedBy: \$ N.self, forKey: . \$ L)" ,
184+ " var \$ L = $containerName .nestedContainer(keyedBy: \$ N.self, forKey: \$ L)" ,
199185 topLevelContainerName,
200186 ClientRuntimeTypes .Serde .Key ,
201- memberName
187+ keyName
202188 )
203- renderEncodeMap(ctx, memberName, topLevelContainerName, targetShape.value , level)
189+ renderEncodeMap(ctx, memberName, topLevelContainerName, targetShape, level)
204190 }
205191 else -> {
206192 val isBoxed = ctx.symbolProvider.toSymbol(targetShape).isBoxed() && targetShape.hasTrait<SparseTrait >()
207- val keyEnumName = if (level == 0 ) " .$memberName " else " ${ClientRuntimeTypes .Serde .Key } (stringValue: $dictKey${level - 1 } )"
208193 if (isBoxed && level == 0 ) {
209194 writer.openBlock(" if let \$ L = \$ L {" , " }" , memberName, memberName) {
210- renderSimpleShape(targetShape, memberName, containerName, keyEnumName , isBoxed)
195+ renderSimpleShape(targetShape, memberName, containerName, keyName , isBoxed)
211196 }
212197 } else {
213- renderSimpleShape(targetShape, memberName, containerName, keyEnumName , isBoxed)
198+ renderSimpleShape(targetShape, memberName, containerName, keyName , isBoxed)
214199 }
215200 }
216201 }
@@ -221,37 +206,27 @@ abstract class MemberShapeEncodeGenerator(
221206 ctx : ProtocolGenerator .GenerationContext ,
222207 mapName : String ,
223208 topLevelContainerName : String ,
224- valueTargetShape : Shape ,
209+ mapShape : MapShape ,
225210 level : Int = 0
226211 ) {
227- val valueIterator = " ${valueTargetShape.id.name.toLowerCase()}$level "
228- val target = when (valueTargetShape) {
229- is MemberShape -> ctx.model.expectShape(valueTargetShape.target)
230- else -> valueTargetShape
231- }
232- writer.openBlock(" for ($dictKey$level , $valueIterator ) in $mapName {" , " }" ) {
233- when (target) {
234- is CollectionShape -> {
235- val nestedTarget = ctx.model.expectShape(target.member.target)
236- renderEncodeMapMember(
237- nestedTarget,
238- valueIterator,
239- topLevelContainerName,
240- level + 1
241- )
212+ val keyIterator = " $dictKey$level "
213+ val valueIterator = " ${mapShape.id.name.toLowerCamelCase()}$level "
214+ val target = ctx.model.expectShape(mapShape.value.target)
215+ val mapIsSparse = mapShape.hasTrait<SparseTrait >()
216+ writer.openBlock(" for ($keyIterator , $valueIterator ) in $mapName {" , " }" ) {
217+ if (mapIsSparse) {
218+ writer.openBlock(" guard let \$ L = \$ L else {" , " }" , valueIterator, valueIterator) {
219+ writer.write(" try \$ L.encodeNil(forKey: \$ L(stringValue: \$ L))" , topLevelContainerName, ClientRuntimeTypes .Serde .Key , keyIterator)
220+ writer.write(" continue" )
242221 }
243- is MapShape -> {
244- val nestedTarget = ctx.model.expectShape(target.value.target)
245- renderEncodeMapMember(
246- nestedTarget,
247- valueIterator,
248- topLevelContainerName,
249- level + 1
250- )
222+ }
223+ when (target) {
224+ is CollectionShape , is MapShape -> {
225+ renderEncodeMapMember(target, valueIterator, topLevelContainerName, level + 1 )
251226 }
252227 else -> {
253228 val keyEnumName = " ${ClientRuntimeTypes .Serde .Key } (stringValue: $dictKey$level )"
254- renderSimpleShape(valueTargetShape , valueIterator, topLevelContainerName, keyEnumName, valueTargetShape .hasTrait(BoxTrait ::class .java))
229+ renderSimpleShape(target , valueIterator, topLevelContainerName, keyEnumName, target .hasTrait(BoxTrait ::class .java))
255230 }
256231 }
257232 }
0 commit comments