Skip to content

Commit

Permalink
Merge pull request #1144 from disneystreaming/union-project-visitor
Browse files Browse the repository at this point in the history
Add Projections and Visitors to Unions
  • Loading branch information
Baccata authored Aug 14, 2023
2 parents 17ac412 + 9bcacd0 commit d2511cd
Show file tree
Hide file tree
Showing 35 changed files with 1,391 additions and 273 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ Introduces alternative code generation for enums and intEnums when they are mark

See https://github.com/disneystreaming/smithy4s/pull/1137

### Union Projections and Visitors

Added convenient methods for working with unions including projectors for each union alternative and a visitor in union companion objects that can be passed to each union's new `accept` method.

See https://github.com/disneystreaming/smithy4s/pull/1144

# 0.17.14

* Only transform AWS shapes named after standard shapes in [#1127](https://github.com/disneystreaming/smithy4s/pull/1127)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,14 +162,24 @@ object DynamoDBOperation {
case ListTablesError.InvalidEndpointExceptionCase(e) => e
}
}
sealed trait ListTablesError extends scala.Product with scala.Serializable {
sealed trait ListTablesError extends scala.Product with scala.Serializable { self =>
@inline final def widen: ListTablesError = this
def $ordinal: Int

object project {
def internalServerError: Option[InternalServerError] = ListTablesError.InternalServerErrorCase.alt.project.lift(self).map(_.internalServerError)
def invalidEndpointException: Option[InvalidEndpointException] = ListTablesError.InvalidEndpointExceptionCase.alt.project.lift(self).map(_.invalidEndpointException)
}

def accept[A](visitor: ListTablesError.Visitor[A]): A = this match {
case value: ListTablesError.InternalServerErrorCase => visitor.internalServerError(value.internalServerError)
case value: ListTablesError.InvalidEndpointExceptionCase => visitor.invalidEndpointException(value.invalidEndpointException)
}
}
object ListTablesError extends ShapeTag.Companion[ListTablesError] {

def internalServerError(internalServerError:InternalServerError): ListTablesError = InternalServerErrorCase(internalServerError)
def invalidEndpointException(invalidEndpointException:InvalidEndpointException): ListTablesError = InvalidEndpointExceptionCase(invalidEndpointException)
def internalServerError(internalServerError: InternalServerError): ListTablesError = InternalServerErrorCase(internalServerError)
def invalidEndpointException(invalidEndpointException: InvalidEndpointException): ListTablesError = InvalidEndpointExceptionCase(invalidEndpointException)

val id: ShapeId = ShapeId("com.amazonaws.dynamodb", "ListTablesError")

Expand All @@ -180,18 +190,31 @@ object DynamoDBOperation {

object InternalServerErrorCase {
val hints: Hints = Hints.empty
val schema: Schema[InternalServerErrorCase] = bijection(InternalServerError.schema.addHints(hints), InternalServerErrorCase(_), _.internalServerError)
val schema: Schema[ListTablesError.InternalServerErrorCase] = bijection(InternalServerError.schema.addHints(hints), ListTablesError.InternalServerErrorCase(_), _.internalServerError)
val alt = schema.oneOf[ListTablesError]("InternalServerError")
}
object InvalidEndpointExceptionCase {
val hints: Hints = Hints.empty
val schema: Schema[InvalidEndpointExceptionCase] = bijection(InvalidEndpointException.schema.addHints(hints), InvalidEndpointExceptionCase(_), _.invalidEndpointException)
val schema: Schema[ListTablesError.InvalidEndpointExceptionCase] = bijection(InvalidEndpointException.schema.addHints(hints), ListTablesError.InvalidEndpointExceptionCase(_), _.invalidEndpointException)
val alt = schema.oneOf[ListTablesError]("InvalidEndpointException")
}

trait Visitor[A] {
def internalServerError(value: InternalServerError): A
def invalidEndpointException(value: InvalidEndpointException): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def internalServerError(value: InternalServerError): A = default
def invalidEndpointException(value: InvalidEndpointException): A = default
}
}

implicit val schema: UnionSchema[ListTablesError] = union(
InternalServerErrorCase.alt,
InvalidEndpointExceptionCase.alt,
ListTablesError.InternalServerErrorCase.alt,
ListTablesError.InvalidEndpointExceptionCase.alt,
){
_.$ordinal
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.union

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

object project {
def checked: Option[String] = CheckedOrUnchecked.CheckedCase.alt.project.lift(self).map(_.checked)
def raw: Option[String] = CheckedOrUnchecked.RawCase.alt.project.lift(self).map(_.raw)
}

def accept[A](visitor: CheckedOrUnchecked.Visitor[A]): A = this match {
case value: CheckedOrUnchecked.CheckedCase => visitor.checked(value.checked)
case value: CheckedOrUnchecked.RawCase => visitor.raw(value.raw)
}
}
object CheckedOrUnchecked extends ShapeTag.Companion[CheckedOrUnchecked] {

def checked(checked:String): CheckedOrUnchecked = CheckedCase(checked)
def raw(raw:String): CheckedOrUnchecked = RawCase(raw)
def checked(checked: String): CheckedOrUnchecked = CheckedCase(checked)
def raw(raw: String): CheckedOrUnchecked = RawCase(raw)

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

Expand All @@ -26,18 +36,31 @@ object CheckedOrUnchecked extends ShapeTag.Companion[CheckedOrUnchecked] {

object CheckedCase {
val hints: Hints = Hints.empty
val schema: Schema[CheckedCase] = bijection(string.addHints(hints).validated(smithy.api.Pattern(s"^\\w+$$")), CheckedCase(_), _.checked)
val schema: Schema[CheckedOrUnchecked.CheckedCase] = bijection(string.addHints(hints).validated(smithy.api.Pattern(s"^\\w+$$")), CheckedOrUnchecked.CheckedCase(_), _.checked)
val alt = schema.oneOf[CheckedOrUnchecked]("checked")
}
object RawCase {
val hints: Hints = Hints.empty
val schema: Schema[RawCase] = bijection(string.addHints(hints), RawCase(_), _.raw)
val schema: Schema[CheckedOrUnchecked.RawCase] = bijection(string.addHints(hints), CheckedOrUnchecked.RawCase(_), _.raw)
val alt = schema.oneOf[CheckedOrUnchecked]("raw")
}

trait Visitor[A] {
def checked(value: String): A
def raw(value: String): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def checked(value: String): A = default
def raw(value: String): A = default
}
}

implicit val schema: Schema[CheckedOrUnchecked] = union(
CheckedCase.alt,
RawCase.alt,
CheckedOrUnchecked.CheckedCase.alt,
CheckedOrUnchecked.RawCase.alt,
){
_.$ordinal
}.withId(id).addHints(hints)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ import smithy4s.schema.Schema.bijection
import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.union

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

object project {
def checked: Option[String] = CheckedOrUnchecked2.CheckedCase.alt.project.lift(self).map(_.checked)
def raw: Option[String] = CheckedOrUnchecked2.RawCase.alt.project.lift(self).map(_.raw)
}

def accept[A](visitor: CheckedOrUnchecked2.Visitor[A]): A = this match {
case value: CheckedOrUnchecked2.CheckedCase => visitor.checked(value.checked)
case value: CheckedOrUnchecked2.RawCase => visitor.raw(value.raw)
}
}
object CheckedOrUnchecked2 extends ShapeTag.Companion[CheckedOrUnchecked2] {

def checked(checked:String): CheckedOrUnchecked2 = CheckedCase(checked)
def raw(raw:String): CheckedOrUnchecked2 = RawCase(raw)
def checked(checked: String): CheckedOrUnchecked2 = CheckedCase(checked)
def raw(raw: String): CheckedOrUnchecked2 = RawCase(raw)

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

Expand All @@ -28,18 +38,31 @@ object CheckedOrUnchecked2 extends ShapeTag.Companion[CheckedOrUnchecked2] {

object CheckedCase {
val hints: Hints = Hints.empty
val schema: Schema[CheckedCase] = bijection(string.addHints(hints).validated(smithy.api.Pattern(s"^\\w+$$")), CheckedCase(_), _.checked)
val schema: Schema[CheckedOrUnchecked2.CheckedCase] = bijection(string.addHints(hints).validated(smithy.api.Pattern(s"^\\w+$$")), CheckedOrUnchecked2.CheckedCase(_), _.checked)
val alt = schema.oneOf[CheckedOrUnchecked2]("checked")
}
object RawCase {
val hints: Hints = Hints.empty
val schema: Schema[RawCase] = bijection(string.addHints(hints), RawCase(_), _.raw)
val schema: Schema[CheckedOrUnchecked2.RawCase] = bijection(string.addHints(hints), CheckedOrUnchecked2.RawCase(_), _.raw)
val alt = schema.oneOf[CheckedOrUnchecked2]("raw")
}

trait Visitor[A] {
def checked(value: String): A
def raw(value: String): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def checked(value: String): A = default
def raw(value: String): A = default
}
}

implicit val schema: Schema[CheckedOrUnchecked2] = union(
CheckedCase.alt,
RawCase.alt,
CheckedOrUnchecked2.CheckedCase.alt,
CheckedOrUnchecked2.RawCase.alt,
){
_.$ordinal
}.withId(id).addHints(hints)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,29 @@ import smithy4s.schema.Schema.string
import smithy4s.schema.Schema.union

@deprecated(message = "A compelling reason", since = "0.0.1")
sealed trait DeprecatedUnion extends scala.Product with scala.Serializable {
sealed trait DeprecatedUnion extends scala.Product with scala.Serializable { self =>
@inline final def widen: DeprecatedUnion = this
def $ordinal: Int

object project {
def s: Option[String] = DeprecatedUnion.SCase.alt.project.lift(self).map(_.s)
def s_V2: Option[String] = DeprecatedUnion.S_V2Case.alt.project.lift(self).map(_.s_V2)
def p: Option[DeprecatedUnion.DeprecatedUnionProductCase] = DeprecatedUnion.DeprecatedUnionProductCase.alt.project.lift(self)
def p2: Option[DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite] = DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite.alt.project.lift(self)
}

def accept[A](visitor: DeprecatedUnion.Visitor[A]): A = this match {
case value: DeprecatedUnion.SCase => visitor.s(value.s)
case value: DeprecatedUnion.S_V2Case => visitor.s_V2(value.s_V2)
case value: DeprecatedUnion.DeprecatedUnionProductCase => visitor.p(value)
case value: DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite => visitor.p2(value)
}
}
object DeprecatedUnion extends ShapeTag.Companion[DeprecatedUnion] {

@deprecated(message = "N/A", since = "N/A")
def s(s:String): DeprecatedUnion = SCase(s)
def s_V2(s_V2:String): DeprecatedUnion = S_V2Case(s_V2)
def s(s: String): DeprecatedUnion = SCase(s)
def s_V2(s_V2: String): DeprecatedUnion = S_V2Case(s_V2)
def deprecatedUnionProductCase():DeprecatedUnionProductCase = DeprecatedUnionProductCase()
@deprecated(message = "N/A", since = "N/A")
def unionProductCaseDeprecatedAtCallSite():UnionProductCaseDeprecatedAtCallSite = UnionProductCaseDeprecatedAtCallSite()
Expand Down Expand Up @@ -67,20 +81,37 @@ object DeprecatedUnion extends ShapeTag.Companion[DeprecatedUnion] {
val hints: Hints = Hints(
smithy.api.Deprecated(message = None, since = None),
)
val schema: Schema[SCase] = bijection(string.addHints(hints), SCase(_), _.s)
val schema: Schema[DeprecatedUnion.SCase] = bijection(string.addHints(hints), DeprecatedUnion.SCase(_), _.s)
val alt = schema.oneOf[DeprecatedUnion]("s")
}
object S_V2Case {
val hints: Hints = Hints.empty
val schema: Schema[S_V2Case] = bijection(string.addHints(hints), S_V2Case(_), _.s_V2)
val schema: Schema[DeprecatedUnion.S_V2Case] = bijection(string.addHints(hints), DeprecatedUnion.S_V2Case(_), _.s_V2)
val alt = schema.oneOf[DeprecatedUnion]("s_V2")
}

trait Visitor[A] {
def s(value: String): A
def s_V2(value: String): A
def p(value: DeprecatedUnion.DeprecatedUnionProductCase): A
def p2(value: DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def s(value: String): A = default
def s_V2(value: String): A = default
def p(value: DeprecatedUnion.DeprecatedUnionProductCase): A = default
def p2(value: DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite): A = default
}
}

implicit val schema: Schema[DeprecatedUnion] = union(
SCase.alt,
S_V2Case.alt,
DeprecatedUnionProductCase.alt,
UnionProductCaseDeprecatedAtCallSite.alt,
DeprecatedUnion.SCase.alt,
DeprecatedUnion.S_V2Case.alt,
DeprecatedUnion.DeprecatedUnionProductCase.alt,
DeprecatedUnion.UnionProductCaseDeprecatedAtCallSite.alt,
){
_.$ordinal
}.withId(id).addHints(hints)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,30 @@ object ErrorHandlingServiceOperation {
case ErrorHandlingOperationError.EHFallbackServerErrorCase(e) => e
}
}
sealed trait ErrorHandlingOperationError extends scala.Product with scala.Serializable {
sealed trait ErrorHandlingOperationError extends scala.Product with scala.Serializable { self =>
@inline final def widen: ErrorHandlingOperationError = this
def $ordinal: Int

object project {
def eHFallbackClientError: Option[EHFallbackClientError] = ErrorHandlingOperationError.EHFallbackClientErrorCase.alt.project.lift(self).map(_.eHFallbackClientError)
def eHServiceUnavailable: Option[EHServiceUnavailable] = ErrorHandlingOperationError.EHServiceUnavailableCase.alt.project.lift(self).map(_.eHServiceUnavailable)
def eHNotFound: Option[EHNotFound] = ErrorHandlingOperationError.EHNotFoundCase.alt.project.lift(self).map(_.eHNotFound)
def eHFallbackServerError: Option[EHFallbackServerError] = ErrorHandlingOperationError.EHFallbackServerErrorCase.alt.project.lift(self).map(_.eHFallbackServerError)
}

def accept[A](visitor: ErrorHandlingOperationError.Visitor[A]): A = this match {
case value: ErrorHandlingOperationError.EHFallbackClientErrorCase => visitor.eHFallbackClientError(value.eHFallbackClientError)
case value: ErrorHandlingOperationError.EHServiceUnavailableCase => visitor.eHServiceUnavailable(value.eHServiceUnavailable)
case value: ErrorHandlingOperationError.EHNotFoundCase => visitor.eHNotFound(value.eHNotFound)
case value: ErrorHandlingOperationError.EHFallbackServerErrorCase => visitor.eHFallbackServerError(value.eHFallbackServerError)
}
}
object ErrorHandlingOperationError extends ShapeTag.Companion[ErrorHandlingOperationError] {

def eHFallbackClientError(eHFallbackClientError:EHFallbackClientError): ErrorHandlingOperationError = EHFallbackClientErrorCase(eHFallbackClientError)
def eHServiceUnavailable(eHServiceUnavailable:EHServiceUnavailable): ErrorHandlingOperationError = EHServiceUnavailableCase(eHServiceUnavailable)
def eHNotFound(eHNotFound:EHNotFound): ErrorHandlingOperationError = EHNotFoundCase(eHNotFound)
def eHFallbackServerError(eHFallbackServerError:EHFallbackServerError): ErrorHandlingOperationError = EHFallbackServerErrorCase(eHFallbackServerError)
def eHFallbackClientError(eHFallbackClientError: EHFallbackClientError): ErrorHandlingOperationError = EHFallbackClientErrorCase(eHFallbackClientError)
def eHServiceUnavailable(eHServiceUnavailable: EHServiceUnavailable): ErrorHandlingOperationError = EHServiceUnavailableCase(eHServiceUnavailable)
def eHNotFound(eHNotFound: EHNotFound): ErrorHandlingOperationError = EHNotFoundCase(eHNotFound)
def eHFallbackServerError(eHFallbackServerError: EHFallbackServerError): ErrorHandlingOperationError = EHFallbackServerErrorCase(eHFallbackServerError)

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

Expand All @@ -125,30 +139,47 @@ object ErrorHandlingServiceOperation {

object EHFallbackClientErrorCase {
val hints: Hints = Hints.empty
val schema: Schema[EHFallbackClientErrorCase] = bijection(EHFallbackClientError.schema.addHints(hints), EHFallbackClientErrorCase(_), _.eHFallbackClientError)
val schema: Schema[ErrorHandlingOperationError.EHFallbackClientErrorCase] = bijection(EHFallbackClientError.schema.addHints(hints), ErrorHandlingOperationError.EHFallbackClientErrorCase(_), _.eHFallbackClientError)
val alt = schema.oneOf[ErrorHandlingOperationError]("EHFallbackClientError")
}
object EHServiceUnavailableCase {
val hints: Hints = Hints.empty
val schema: Schema[EHServiceUnavailableCase] = bijection(EHServiceUnavailable.schema.addHints(hints), EHServiceUnavailableCase(_), _.eHServiceUnavailable)
val schema: Schema[ErrorHandlingOperationError.EHServiceUnavailableCase] = bijection(EHServiceUnavailable.schema.addHints(hints), ErrorHandlingOperationError.EHServiceUnavailableCase(_), _.eHServiceUnavailable)
val alt = schema.oneOf[ErrorHandlingOperationError]("EHServiceUnavailable")
}
object EHNotFoundCase {
val hints: Hints = Hints.empty
val schema: Schema[EHNotFoundCase] = bijection(EHNotFound.schema.addHints(hints), EHNotFoundCase(_), _.eHNotFound)
val schema: Schema[ErrorHandlingOperationError.EHNotFoundCase] = bijection(EHNotFound.schema.addHints(hints), ErrorHandlingOperationError.EHNotFoundCase(_), _.eHNotFound)
val alt = schema.oneOf[ErrorHandlingOperationError]("EHNotFound")
}
object EHFallbackServerErrorCase {
val hints: Hints = Hints.empty
val schema: Schema[EHFallbackServerErrorCase] = bijection(EHFallbackServerError.schema.addHints(hints), EHFallbackServerErrorCase(_), _.eHFallbackServerError)
val schema: Schema[ErrorHandlingOperationError.EHFallbackServerErrorCase] = bijection(EHFallbackServerError.schema.addHints(hints), ErrorHandlingOperationError.EHFallbackServerErrorCase(_), _.eHFallbackServerError)
val alt = schema.oneOf[ErrorHandlingOperationError]("EHFallbackServerError")
}

trait Visitor[A] {
def eHFallbackClientError(value: EHFallbackClientError): A
def eHServiceUnavailable(value: EHServiceUnavailable): A
def eHNotFound(value: EHNotFound): A
def eHFallbackServerError(value: EHFallbackServerError): A
}

object Visitor {
trait Default[A] extends Visitor[A] {
def default: A
def eHFallbackClientError(value: EHFallbackClientError): A = default
def eHServiceUnavailable(value: EHServiceUnavailable): A = default
def eHNotFound(value: EHNotFound): A = default
def eHFallbackServerError(value: EHFallbackServerError): A = default
}
}

implicit val schema: UnionSchema[ErrorHandlingOperationError] = union(
EHFallbackClientErrorCase.alt,
EHServiceUnavailableCase.alt,
EHNotFoundCase.alt,
EHFallbackServerErrorCase.alt,
ErrorHandlingOperationError.EHFallbackClientErrorCase.alt,
ErrorHandlingOperationError.EHServiceUnavailableCase.alt,
ErrorHandlingOperationError.EHNotFoundCase.alt,
ErrorHandlingOperationError.EHFallbackServerErrorCase.alt,
){
_.$ordinal
}
Expand Down
Loading

0 comments on commit d2511cd

Please sign in to comment.