Skip to content

Commit

Permalink
simplify, add Validator derivation and reuse, add Validator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ThijsBroersen committed Jun 14, 2024
1 parent 816841f commit 753d62e
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 5 deletions.
9 changes: 7 additions & 2 deletions core/src/main/scala-3/sttp/tapir/macros/CodecMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ trait CodecMacros {
inline def derivedEnumerationValueCustomise[L, T <: scala.Enumeration#Value]: CreateDerivedEnumerationCodec[L, T] =
new CreateDerivedEnumerationCodec(derivedEnumerationValueValidator[T], SchemaAnnotations.derived[T])

/** Creates a codec for a string-based union of constant values, where the validator is derived using
* [[sttp.tapir.Validator.derivedStringBasedUnionEnumeration]]. This requires that the union is a union of string literals.
*
* @tparam T
* The type of the union.
*/
inline given derivedStringBasedUnionEnumeration[T](using IsUnionOf[String, T]): Codec[String, T, TextPlain] =
lazy val values = UnionDerivation.constValueUnionTuple[String, T]
lazy val validator = Validator.enumeration(values.toList.asInstanceOf[List[T]])
lazy val validator = Validator.derivedStringBasedUnionEnumeration[T]
Codec.string.validate(validator.asInstanceOf[Validator[String]]).map(_.asInstanceOf[T])(_.asInstanceOf[String])

/** A default codec for enumerations, which returns a string-based enumeration codec, using the enum's `.toString` to encode values, and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ object SchemaCompanionMacrosExtensions extends SchemaCompanionMacrosExtensions

trait SchemaCompanionMacrosExtensions:
inline given derivedStringBasedUnionEnumeration[S](using IsUnionOf[String, S]): Schema[S] =
lazy val values = UnionDerivation.constValueUnionTuple[String, S]
lazy val validator = Validator.enumeration(values.toList.asInstanceOf[List[S]])
lazy val validator = Validator.derivedStringBasedUnionEnumeration[S]
Schema
.string[S]
.name(SName(values.toList.mkString("_or_")))
.name(SName(validator.possibleValues.toList.mkString("_or_")))
.validate(validator)
5 changes: 5 additions & 0 deletions core/src/main/scala-3/sttp/tapir/macros/ValidatorMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ trait ValidatorMacros {
* first place (the decoder has no other option than to fail).
*/
inline def derivedEnumeration[T]: Validator.Enumeration[T] = ${ ValidatorMacros.derivedEnumerationImpl[T] }

inline def derivedStringBasedUnionEnumeration[T](using IsUnionOf[String, T]): Validator.Enumeration[T] = {
lazy val values = UnionDerivation.constValueUnionTuple[String, T]
Validator.enumeration(values.toList.asInstanceOf[List[T]])
}
}

private[tapir] object ValidatorMacros {
Expand Down
10 changes: 10 additions & 0 deletions core/src/test/scala-3/sttp/tapir/ValidatorScala3EnumTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ class ValidatorScala3EnumTest extends AnyFlatSpec with Matchers {
""")
}

it should "derive a validator for a string-based union type" in {
// given
val validator = Validator.derivedStringBasedUnionEnumeration["Apple" | "Banana"].asInstanceOf[Validator.Primitive[String]]

// then
validator.doValidate("Apple") shouldBe ValidationResult.Valid
validator.doValidate("Banana") shouldBe ValidationResult.Valid
validator.doValidate("Orange") shouldBe ValidationResult.Invalid()
}

}

enum ColorEnum {
Expand Down

0 comments on commit 753d62e

Please sign in to comment.