Skip to content

Commit

Permalink
Merge pull request #1446 from disneystreaming/add-untagged-document-d…
Browse files Browse the repository at this point in the history
…ecoder

support for untagged in DocumentDecoderSchemaVisitor
  • Loading branch information
Baccata committed Mar 18, 2024
2 parents f5db8d5 + 8ffa2e2 commit 141bf99
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
@@ -1,5 +1,6 @@
# 0.18.14

* Add support for decoding Document representations of untagged unions
* Update aws-http4s clients using json to have a maxArity of Int.MaxValue

# 0.18.13
Expand Down
25 changes: 25 additions & 0 deletions modules/bootstrapped/test/src/smithy4s/DocumentSpec.scala
Expand Up @@ -22,6 +22,7 @@ import smithy4s.example.IntList
import alloy.Discriminated
import munit._
import smithy4s.example.OperationOutput
import alloy.Untagged

class DocumentSpec() extends FunSuite {

Expand Down Expand Up @@ -138,6 +139,30 @@ class DocumentSpec() extends FunSuite {
expect.same(roundTripped, Right(fooOrBar))
}

test("untagged unions encoding") {
implicit val eitherSchema: Schema[Either[Long, String]] = {
val left = Schema.long
val right = Schema.string

Schema
.either(left, right)
.addHints(
Untagged()
)
}
val longOrString: Either[Long, String] = Right("hello")

val document = Document.encode(longOrString)
import Document._
val expectedDocument =
Document.fromString("hello")

val roundTripped = Document.decode[Either[Long, String]](document)

expect.same(document, expectedDocument)
expect.same(roundTripped, Right(longOrString))
}

test("discriminated unions encoding - empty structure alternative") {
val fooOrBaz: Either[Foo, Baz] = Right(Baz())

Expand Down
Expand Up @@ -33,6 +33,7 @@ import smithy4s.schema._
import java.util.Base64
import java.util.UUID
import scala.collection.immutable.ListMap
import alloy.Untagged

trait DocumentDecoder[A] { self =>
def apply(history: List[PayloadPath.Segment], document: Document): A
Expand Down Expand Up @@ -445,6 +446,34 @@ class DocumentDecoderSchemaVisitor(

}

private def untaggedUnion[S](
decoders: DecoderMap[S]
): DocumentDecoder[S] = {
val decodersList = decoders.values.toList
val len = decodersList.length

handleUnion { (pp: List[PayloadPath.Segment], document: Document) =>
var z: S = null.asInstanceOf[S]
var i = 0
while (z == null && i < len) {
try {
z = decodersList(i)(pp, document)
} catch {
case _: Throwable => i += 1
}
}
if (z == null) {
throw new PayloadError(
PayloadPath(pp.reverse),
"Union",
"No valid alternatives found for untagged union"
)
} else {
z
}
}
}

override def union[U](
shapeId: ShapeId,
hints: Hints,
Expand All @@ -466,6 +495,8 @@ class DocumentDecoderSchemaVisitor(
hints match {
case Discriminated.hint(discriminated) =>
discriminatedUnion(discriminated, decoders)
case Untagged.hint(_) =>
untaggedUnion(decoders)
case _ =>
taggedUnion(decoders)
}
Expand Down

0 comments on commit 141bf99

Please sign in to comment.