Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.internals.StructurePatternRefinementProvider._
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object NestedInnerUnionPattern extends Newtype[NestedInnerUnionTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedInnerUnionPattern")
val hints: Hints = Hints(
Hints.dynamic(ShapeId("alloy", "structurePattern"), smithy4s.Document.obj("pattern" -> smithy4s.Document.fromString("{label}:{value}"), "target" -> smithy4s.Document.fromString("smithy4s.example#NestedInnerUnionTarget"))),
)
val underlyingSchema: Schema[NestedInnerUnionTarget] = string.refined[NestedInnerUnionTarget](alloy.StructurePattern(pattern = "{label}:{value}", target = smithy4s.ShapeId(namespace = "smithy4s.example", name = "NestedInnerUnionTarget"))).withId(id).addHints(hints)
implicit val schema: Schema[NestedInnerUnionPattern] = bijection(underlyingSchema, asBijection)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.int
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.union

sealed trait NestedInnerUnionTarget extends scala.Product with scala.Serializable { self =>
@inline final def widen: NestedInnerUnionTarget = this
def $ordinal: Int

object project {
def str: Option[String] = NestedInnerUnionTarget.StrCase.alt.project.lift(self).map(_.str)
def num: Option[Int] = NestedInnerUnionTarget.NumCase.alt.project.lift(self).map(_.num)
}

def accept[A](visitor: NestedInnerUnionTarget.Visitor[A]): A = this match {
case value: NestedInnerUnionTarget.StrCase => visitor.str(value.str)
case value: NestedInnerUnionTarget.NumCase => visitor.num(value.num)
}
}
object NestedInnerUnionTarget extends ShapeTag.Companion[NestedInnerUnionTarget] {

def str(str: String): NestedInnerUnionTarget = StrCase(str)
def num(num: Int): NestedInnerUnionTarget = NumCase(num)

val id: ShapeId = ShapeId("smithy4s.example", "NestedInnerUnionTarget")

val hints: Hints = Hints.empty

final case class StrCase(str: String) extends NestedInnerUnionTarget { final def $ordinal: Int = 0 }
final case class NumCase(num: Int) extends NestedInnerUnionTarget { final def $ordinal: Int = 1 }

object StrCase {
val hints: Hints = Hints.empty
val schema: Schema[NestedInnerUnionTarget.StrCase] = bijection(string.addHints(hints), NestedInnerUnionTarget.StrCase(_), _.str)
val alt = schema.oneOf[NestedInnerUnionTarget]("str")
}
object NumCase {
val hints: Hints = Hints.empty
val schema: Schema[NestedInnerUnionTarget.NumCase] = bijection(int.addHints(hints), NestedInnerUnionTarget.NumCase(_), _.num)
val alt = schema.oneOf[NestedInnerUnionTarget]("num")
}

trait Visitor[A] {
def str(value: String): A
def num(value: Int): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def str(value: String): A = default
def num(value: Int): A = default
}
}

implicit val schema: Schema[NestedInnerUnionTarget] = union[NestedInnerUnionTarget](
NestedInnerUnionTarget.StrCase.alt,
NestedInnerUnionTarget.NumCase.alt,
){
_.$ordinal
}.withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.internals.StructurePatternRefinementProvider._
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object NestedMiddlePattern extends Newtype[NestedMiddlePatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedMiddlePattern")
val hints: Hints = Hints(
Hints.dynamic(ShapeId("alloy", "structurePattern"), smithy4s.Document.obj("pattern" -> smithy4s.Document.fromString("{id}|{choice}"), "target" -> smithy4s.Document.fromString("smithy4s.example#NestedMiddlePatternTarget"))),
)
val underlyingSchema: Schema[NestedMiddlePatternTarget] = string.refined[NestedMiddlePatternTarget](alloy.StructurePattern(pattern = "{id}|{choice}", target = smithy4s.ShapeId(namespace = "smithy4s.example", name = "NestedMiddlePatternTarget"))).withId(id).addHints(hints)
implicit val schema: Schema[NestedMiddlePattern] = bijection(underlyingSchema, asBijection)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.int
import smithy4s.schema.Schema.struct

final case class NestedMiddlePatternTarget(id: Int, choice: NestedInnerUnionPattern)

object NestedMiddlePatternTarget extends ShapeTag.Companion[NestedMiddlePatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedMiddlePatternTarget")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(id: Int, choice: NestedInnerUnionPattern): NestedMiddlePatternTarget = NestedMiddlePatternTarget(id, choice)

implicit val schema: Schema[NestedMiddlePatternTarget] = struct[NestedMiddlePatternTarget](
int.required[NestedMiddlePatternTarget]("id", _.id),
NestedInnerUnionPattern.schema.required[NestedMiddlePatternTarget]("choice", _.choice),
)(make).withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.internals.StructurePatternRefinementProvider._
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object NestedStructurePattern extends Newtype[NestedStructurePatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedStructurePattern")
val hints: Hints = Hints(
Hints.dynamic(ShapeId("alloy", "structurePattern"), smithy4s.Document.obj("pattern" -> smithy4s.Document.fromString("{name}/{inner}"), "target" -> smithy4s.Document.fromString("smithy4s.example#NestedStructurePatternTarget"))),
)
val underlyingSchema: Schema[NestedStructurePatternTarget] = string.refined[NestedStructurePatternTarget](alloy.StructurePattern(pattern = "{name}/{inner}", target = smithy4s.ShapeId(namespace = "smithy4s.example", name = "NestedStructurePatternTarget"))).withId(id).addHints(hints)
implicit val schema: Schema[NestedStructurePattern] = bijection(underlyingSchema, asBijection)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.struct

final case class NestedStructurePatternTarget(name: String, inner: TestStructurePattern)

object NestedStructurePatternTarget extends ShapeTag.Companion[NestedStructurePatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedStructurePatternTarget")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(name: String, inner: TestStructurePattern): NestedStructurePatternTarget = NestedStructurePatternTarget(name, inner)

implicit val schema: Schema[NestedStructurePatternTarget] = struct[NestedStructurePatternTarget](
string.required[NestedStructurePatternTarget]("name", _.name),
TestStructurePattern.schema.required[NestedStructurePatternTarget]("inner", _.inner),
)(make).withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.internals.StructurePatternRefinementProvider._
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object NestedTopPattern extends Newtype[NestedTopPatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedTopPattern")
val hints: Hints = Hints(
Hints.dynamic(ShapeId("alloy", "structurePattern"), smithy4s.Document.obj("pattern" -> smithy4s.Document.fromString("{tenant}/{resource}"), "target" -> smithy4s.Document.fromString("smithy4s.example#NestedTopPatternTarget"))),
)
val underlyingSchema: Schema[NestedTopPatternTarget] = string.refined[NestedTopPatternTarget](alloy.StructurePattern(pattern = "{tenant}/{resource}", target = smithy4s.ShapeId(namespace = "smithy4s.example", name = "NestedTopPatternTarget"))).withId(id).addHints(hints)
implicit val schema: Schema[NestedTopPattern] = bijection(underlyingSchema, asBijection)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.struct

final case class NestedTopPatternTarget(tenant: String, resource: NestedMiddlePattern)

object NestedTopPatternTarget extends ShapeTag.Companion[NestedTopPatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedTopPatternTarget")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(tenant: String, resource: NestedMiddlePattern): NestedTopPatternTarget = NestedTopPatternTarget(tenant, resource)

implicit val schema: Schema[NestedTopPatternTarget] = struct[NestedTopPatternTarget](
string.required[NestedTopPatternTarget]("tenant", _.tenant),
NestedMiddlePattern.schema.required[NestedTopPatternTarget]("resource", _.resource),
)(make).withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Newtype
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.internals.StructurePatternRefinementProvider._
import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string

object NestedUnionPattern extends Newtype[NestedUnionPatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedUnionPattern")
val hints: Hints = Hints(
Hints.dynamic(ShapeId("alloy", "structurePattern"), smithy4s.Document.obj("pattern" -> smithy4s.Document.fromString("{prefix}/{tagged}"), "target" -> smithy4s.Document.fromString("smithy4s.example#NestedUnionPatternTarget"))),
)
val underlyingSchema: Schema[NestedUnionPatternTarget] = string.refined[NestedUnionPatternTarget](alloy.StructurePattern(pattern = "{prefix}/{tagged}", target = smithy4s.ShapeId(namespace = "smithy4s.example", name = "NestedUnionPatternTarget"))).withId(id).addHints(hints)
implicit val schema: Schema[NestedUnionPattern] = bijection(underlyingSchema, asBijection)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package smithy4s.example

import smithy4s.Hints
import smithy4s.Schema
import smithy4s.ShapeId
import smithy4s.ShapeTag
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.struct

final case class NestedUnionPatternTarget(prefix: String, tagged: TestUnionPattern)

object NestedUnionPatternTarget extends ShapeTag.Companion[NestedUnionPatternTarget] {
val id: ShapeId = ShapeId("smithy4s.example", "NestedUnionPatternTarget")

val hints: Hints = Hints.empty

// constructor using the original order from the spec
private def make(prefix: String, tagged: TestUnionPattern): NestedUnionPatternTarget = NestedUnionPatternTarget(prefix, tagged)

implicit val schema: Schema[NestedUnionPatternTarget] = struct[NestedUnionPatternTarget](
string.required[NestedUnionPatternTarget]("prefix", _.prefix),
TestUnionPattern.schema.required[NestedUnionPatternTarget]("tagged", _.tagged),
)(make).withId(id).addHints(hints)
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ package object example {
type MyLocalTime = smithy4s.example.MyLocalTime.Type
type MyOffsetDateTime = smithy4s.example.MyOffsetDateTime.Type
type Name = smithy4s.example.Name.Type
type NestedInnerUnionPattern = smithy4s.example.NestedInnerUnionPattern.Type
type NestedMiddlePattern = smithy4s.example.NestedMiddlePattern.Type
type NestedStructurePattern = smithy4s.example.NestedStructurePattern.Type
type NestedTopPattern = smithy4s.example.NestedTopPattern.Type
type NestedUnionPattern = smithy4s.example.NestedUnionPattern.Type
type NonEmptyCandies = smithy4s.example.NonEmptyCandies.Type
type NonEmptyMapNumbers = smithy4s.example.NonEmptyMapNumbers.Type
type NonEmptyNames = smithy4s.example.NonEmptyNames.Type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,117 @@ final class StructurePatternRefinementProviderSpec extends FunSuite {
runDecode("{label}:{value}", "one:", one, shouldFail = true)
}

// Nested structure patterns using generated types from structure_pattern.smithy

test("nested structure pattern - encoding (structure in structure)") {
import smithy4s.example._
val inner = TestStructurePattern(TestStructurePatternTarget("foo", 42))
val target = NestedStructurePatternTarget("hello", inner)
runEncode("{name}/{inner}", target, "hello/foo-42")
}

test("nested structure pattern - decoding (structure in structure)") {
import smithy4s.example._
val inner = TestStructurePattern(TestStructurePatternTarget("foo", 42))
val target = NestedStructurePatternTarget("hello", inner)
runDecode("{name}/{inner}", "hello/foo-42", target)
runDecode("{name}/{inner}", "hello/foo-", target, shouldFail = true)
runDecode("{name}/{inner}", "hello/", target, shouldFail = true)
}

test("nested structure pattern - encoding (union in structure)") {
import smithy4s.example._
val strVal = NestedUnionPatternTarget(
"abc",
TestUnionPattern(TestUnionPatternTarget.one("hi"))
)
val numVal = NestedUnionPatternTarget(
"abc",
TestUnionPattern(TestUnionPatternTarget.two(99))
)
runEncode("{prefix}/{tagged}", strVal, "abc/one:hi")
runEncode("{prefix}/{tagged}", numVal, "abc/two:99")
}

test("nested structure pattern - decoding (union in structure)") {
import smithy4s.example._
val strVal = NestedUnionPatternTarget(
"abc",
TestUnionPattern(TestUnionPatternTarget.one("hi"))
)
val numVal = NestedUnionPatternTarget(
"abc",
TestUnionPattern(TestUnionPatternTarget.two(99))
)
runDecode("{prefix}/{tagged}", "abc/one:hi", strVal)
runDecode("{prefix}/{tagged}", "abc/two:99", numVal)
runDecode("{prefix}/{tagged}", "abc/unknown:x", strVal, shouldFail = true)
runDecode("{prefix}/{tagged}", "abc/one:", strVal, shouldFail = true)
}

test(
"nested structure pattern - encoding (structure wrapping structure wrapping union)"
) {
import smithy4s.example._
val value = NestedTopPatternTarget(
"acme",
NestedMiddlePattern(
NestedMiddlePatternTarget(
7,
NestedInnerUnionPattern(NestedInnerUnionTarget.str("hello"))
)
)
)
runEncode("{tenant}/{resource}", value, "acme/7|str:hello")

val value2 = NestedTopPatternTarget(
"acme",
NestedMiddlePattern(
NestedMiddlePatternTarget(
7,
NestedInnerUnionPattern(NestedInnerUnionTarget.num(42))
)
)
)
runEncode("{tenant}/{resource}", value2, "acme/7|num:42")
}

test(
"nested structure pattern - decoding (structure wrapping structure wrapping union)"
) {
import smithy4s.example._
val value = NestedTopPatternTarget(
"acme",
NestedMiddlePattern(
NestedMiddlePatternTarget(
7,
NestedInnerUnionPattern(NestedInnerUnionTarget.str("hello"))
)
)
)
runDecode("{tenant}/{resource}", "acme/7|str:hello", value)

val value2 = NestedTopPatternTarget(
"acme",
NestedMiddlePattern(
NestedMiddlePatternTarget(
7,
NestedInnerUnionPattern(NestedInnerUnionTarget.num(42))
)
)
)
runDecode("{tenant}/{resource}", "acme/7|num:42", value2)

runDecode(
"{tenant}/{resource}",
"acme/7|unknown:x",
value,
shouldFail = true
)
runDecode("{tenant}/{resource}", "acme/7|str:", value, shouldFail = true)
runDecode("{tenant}/{resource}", "acme/", value, shouldFail = true)
}

private def runEncode[A](pattern: String, input: A, expect: String)(implicit
sch: Schema[A],
loc: Location
Expand Down
Loading
Loading