Skip to content

Commit

Permalink
fix: add missing codegen support for Smithy 1.23 upgrade (#691)
Browse files Browse the repository at this point in the history
  • Loading branch information
ianbotsf authored Aug 18, 2022
1 parent fd3c846 commit 8f3279a
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public sealed class SerialKind {
public object Char : SerialKind()
public object Short : SerialKind()
public object Float : SerialKind()
public object Enum : SerialKind()
public object IntEnum : SerialKind()
public object Map : SerialKind()
public object List : SerialKind()
public object Struct : SerialKind()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ val Shape.isDeprecated: Boolean
* https://awslabs.github.io/smithy/1.0/spec/core/constraint-traits.html#enum-trait
*/
val Shape.isEnum: Boolean
get() = isStringShape && hasTrait<@Suppress("DEPRECATION") software.amazon.smithy.model.traits.EnumTrait>()
get() =
isStringShape && hasTrait<@Suppress("DEPRECATION") software.amazon.smithy.model.traits.EnumTrait>() ||
isEnumShape ||
isIntEnumShape

/**
* Test if a shape is an error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import software.amazon.smithy.codegen.core.SymbolProvider
import software.amazon.smithy.kotlin.codegen.core.*
import software.amazon.smithy.kotlin.codegen.model.SymbolProperty
import software.amazon.smithy.kotlin.codegen.model.hasTrait
import software.amazon.smithy.kotlin.codegen.model.isEnum
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.node.*
import software.amazon.smithy.model.shapes.*
Expand Down Expand Up @@ -97,17 +98,14 @@ class ShapeValueGenerator(
RuntimeTypes.Core.Content.StringContent,
RuntimeTypes.Core.Content.toByteArray,
)
val suffix = when (shape.type) {
ShapeType.STRING -> {
if (shape.hasTrait<@Suppress("DEPRECATION") software.amazon.smithy.model.traits.EnumTrait>()) {
val symbol = symbolProvider.toSymbol(shape)
writer.writeInline("#L.fromValue(", symbol.name)
")"
} else {
""
}
val suffix = when {
shape.isEnum -> {
val symbol = symbolProvider.toSymbol(shape)
writer.writeInline("#L.fromValue(", symbol.name)
")"
}
ShapeType.BLOB -> {

shape.type == ShapeType.BLOB -> {
if (shape.hasTrait<StreamingTrait>()) {
writer.addImport(blobHandlingSymbols)
writer.writeInline("StringContent(")
Expand All @@ -117,6 +115,7 @@ class ShapeValueGenerator(
".encodeAsByteArray()"
}
}

else -> ""
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
writer.write("builder.body = #T(input.#L)", RuntimeTypes.Http.ByteArrayContent, memberName)
}
}

ShapeType.STRING -> {
val contents = if (target.isEnum) {
"$memberName.value"
Expand All @@ -445,13 +446,26 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
}
writer.write("builder.body = #T(input.#L.#T())", RuntimeTypes.Http.ByteArrayContent, contents, KotlinTypes.Text.encodeToByteArray)
}

ShapeType.ENUM ->
writer.write(
"builder.body = #T(input.#L.value.#T())",
RuntimeTypes.Http.ByteArrayContent,
memberName,
KotlinTypes.Text.encodeToByteArray,
)

ShapeType.INT_ENUM -> throw CodegenException("IntEnum is not supported until Smithy 2.0")

ShapeType.STRUCTURE, ShapeType.UNION, ShapeType.DOCUMENT -> {
val sdg = structuredDataSerializer(ctx)
val payloadSerializerFn = sdg.payloadSerializer(ctx, binding.member)
writer.write("val payload = #T(input.#L)", payloadSerializerFn, memberName)
writer.write("builder.body = #T(payload)", RuntimeTypes.Http.ByteArrayContent)
}
else -> throw CodegenException("member shape ${binding.member} serializer not implemented yet")

else ->
throw CodegenException("member shape ${binding.member} (${target.type}) serializer not implemented yet")
}
writer.closeBlock("}")
}
Expand Down Expand Up @@ -869,16 +883,21 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
val targetSymbol = ctx.symbolProvider.toSymbol(target)
when (target.type) {
ShapeType.STRING -> {
writer
.addImport(RuntimeTypes.Http.readAll)
.write("val contents = response.body.#T()?.decodeToString()", RuntimeTypes.Http.readAll)
writer.write("val contents = response.body.#T()?.decodeToString()", RuntimeTypes.Http.readAll)
if (target.isEnum) {
writer.addImport(targetSymbol)
writer.write("builder.$memberName = contents?.let { #T.fromValue(it) }", targetSymbol)
} else {
writer.write("builder.$memberName = contents")
}
}

ShapeType.ENUM -> {
writer.write("val contents = response.body.#T()?.decodeToString()", RuntimeTypes.Http.readAll)
writer.write("builder.#L = contents?.let { #T.fromValue(it) }", memberName, targetSymbol)
}

ShapeType.INT_ENUM -> throw CodegenException("IntEnum is not supported until Smithy 2.0")

ShapeType.BLOB -> {
val isBinaryStream = target.hasTrait<StreamingTrait>()
val conversion = if (isBinaryStream) {
Expand All @@ -890,6 +909,7 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
}
writer.write("builder.$memberName = response.body.$conversion")
}

ShapeType.STRUCTURE, ShapeType.UNION, ShapeType.DOCUMENT -> {
// delegate to the payload deserializer
val sdg = structuredDataParser(ctx)
Expand All @@ -900,7 +920,9 @@ abstract class HttpBindingProtocolGenerator : ProtocolGenerator {
write("builder.#L = #T(payload)", memberName, payloadDeserializerFn)
}
}
else -> throw CodegenException("member shape ${binding.member} deserializer not implemented")

else ->
throw CodegenException("member shape ${binding.member} (${target.type}) deserializer not implemented")
}

writer.openBlock("")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ package software.amazon.smithy.kotlin.codegen.rendering.serde

import software.amazon.smithy.codegen.core.CodegenException
import software.amazon.smithy.kotlin.codegen.core.*
import software.amazon.smithy.kotlin.codegen.model.SymbolProperty
import software.amazon.smithy.kotlin.codegen.model.hasTrait
import software.amazon.smithy.kotlin.codegen.model.isSparse
import software.amazon.smithy.kotlin.codegen.model.targetOrSelf
import software.amazon.smithy.kotlin.codegen.model.*
import software.amazon.smithy.kotlin.codegen.rendering.protocol.ProtocolGenerator
import software.amazon.smithy.model.shapes.*
import software.amazon.smithy.model.traits.SparseTrait
Expand Down Expand Up @@ -87,10 +84,11 @@ open class DeserializeStructGenerator(
ShapeType.LIST,
ShapeType.SET,
-> renderListMemberDeserializer(memberShape, targetShape as CollectionShape)

ShapeType.MAP -> renderMapMemberDeserializer(memberShape, targetShape as MapShape)

ShapeType.STRUCTURE,
ShapeType.UNION,
-> renderShapeDeserializer(memberShape)
ShapeType.BLOB,
ShapeType.BOOLEAN,
ShapeType.STRING,
Expand All @@ -104,7 +102,11 @@ open class DeserializeStructGenerator(
ShapeType.DOCUMENT,
ShapeType.BIG_DECIMAL,
ShapeType.BIG_INTEGER,
ShapeType.ENUM,
-> renderShapeDeserializer(memberShape)

ShapeType.INT_ENUM -> error("IntEnum is not supported until Smithy 2.0")

else -> error("Unexpected shape type: ${targetShape.type}")
}
}
Expand Down Expand Up @@ -178,14 +180,20 @@ open class DeserializeStructGenerator(
ShapeType.BLOB,
ShapeType.DOCUMENT,
ShapeType.TIMESTAMP,
ShapeType.ENUM,
-> renderEntry(elementShape, nestingLevel, isSparse, parentMemberName)

ShapeType.SET,
ShapeType.LIST,
-> renderListEntry(rootMemberShape, elementShape as CollectionShape, nestingLevel, isSparse, parentMemberName)

ShapeType.MAP -> renderMapEntry(rootMemberShape, elementShape as MapShape, nestingLevel, isSparse, parentMemberName)
ShapeType.UNION,
ShapeType.STRUCTURE,
-> renderNestedStructureEntry(elementShape, nestingLevel, isSparse, parentMemberName)

ShapeType.INT_ENUM -> error("IntEnum is not supported until Smithy 2.0")

else -> error("Unhandled type ${elementShape.type}")
}
}
Expand Down Expand Up @@ -383,14 +391,20 @@ open class DeserializeStructGenerator(
ShapeType.BLOB,
ShapeType.DOCUMENT,
ShapeType.TIMESTAMP,
ShapeType.ENUM,
-> renderElement(elementShape, nestingLevel, isSparse, parentMemberName)

ShapeType.LIST,
ShapeType.SET,
-> renderListElement(rootMemberShape, elementShape as CollectionShape, nestingLevel, parentMemberName)

ShapeType.MAP -> renderMapElement(rootMemberShape, elementShape as MapShape, nestingLevel, parentMemberName)
ShapeType.UNION,
ShapeType.STRUCTURE,
-> renderNestedStructureElement(elementShape, nestingLevel, isSparse, parentMemberName)

ShapeType.INT_ENUM -> error("IntEnum is not supported until Smithy 2.0")

else -> error("Unhandled type ${elementShape.type}")
}
}
Expand Down Expand Up @@ -510,20 +524,22 @@ open class DeserializeStructGenerator(
// target shape type to deserialize is either the shape itself or member.target
val target = shape.targetOrSelf(ctx.model)

return when (target.type) {
ShapeType.BOOLEAN -> "deserializeBoolean()"
ShapeType.BYTE -> "deserializeByte()"
ShapeType.SHORT -> "deserializeShort()"
ShapeType.INTEGER -> "deserializeInt()"
ShapeType.LONG -> "deserializeLong()"
ShapeType.FLOAT -> "deserializeFloat()"
ShapeType.DOUBLE -> "deserializeDouble()"
ShapeType.DOCUMENT -> "deserializeDocument()"
ShapeType.BLOB -> {
return when {
target.type == ShapeType.BOOLEAN -> "deserializeBoolean()"
target.type == ShapeType.BYTE -> "deserializeByte()"
target.type == ShapeType.SHORT -> "deserializeShort()"
target.type == ShapeType.INTEGER -> "deserializeInt()"
target.type == ShapeType.LONG -> "deserializeLong()"
target.type == ShapeType.FLOAT -> "deserializeFloat()"
target.type == ShapeType.DOUBLE -> "deserializeDouble()"
target.type == ShapeType.DOCUMENT -> "deserializeDocument()"

target.type == ShapeType.BLOB -> {
writer.addImport("decodeBase64Bytes", KotlinDependency.UTILS)
"deserializeString().decodeBase64Bytes()"
}
ShapeType.TIMESTAMP -> {

target.type == ShapeType.TIMESTAMP -> {
writer.addImport(RuntimeTypes.Core.Instant)
val tsFormat = shape
.getTrait(TimestampFormatTrait::class.java)
Expand All @@ -537,19 +553,21 @@ open class DeserializeStructGenerator(
else -> throw CodegenException("unknown timestamp format: $tsFormat")
}
}
ShapeType.STRING -> when {
target.hasTrait<@Suppress("DEPRECATION") software.amazon.smithy.model.traits.EnumTrait>() -> {
val enumSymbol = ctx.symbolProvider.toSymbol(target)
writer.addImport(enumSymbol)
"deserializeString().let { ${enumSymbol.name}.fromValue(it) }"
}
else -> "deserializeString()"

target.isEnum -> {
val enumSymbol = ctx.symbolProvider.toSymbol(target)
writer.addImport(enumSymbol)
"deserializeString().let { ${enumSymbol.name}.fromValue(it) }"
}
ShapeType.STRUCTURE, ShapeType.UNION -> {

target.type == ShapeType.STRING -> "deserializeString()"

target.type == ShapeType.STRUCTURE || target.type == ShapeType.UNION -> {
val symbol = ctx.symbolProvider.toSymbol(target)
val deserializerName = symbol.documentDeserializerName()
"$deserializerName(deserializer)"
}

else -> throw CodegenException("unknown deserializer for member: $shape; target: $target")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ fun Shape.serialKind(): String = when (this.type) {
ShapeType.FLOAT -> "SerialKind.Float"
ShapeType.DOUBLE -> "SerialKind.Double"
ShapeType.STRING -> "SerialKind.String"
ShapeType.ENUM -> "SerialKind.Enum"
ShapeType.INT_ENUM -> "SerialKind.IntEnum"
ShapeType.BLOB -> "SerialKind.Blob"
ShapeType.TIMESTAMP -> "SerialKind.Timestamp"
ShapeType.DOCUMENT -> "SerialKind.Document"
Expand Down
Loading

0 comments on commit 8f3279a

Please sign in to comment.