All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sttp.tapir.macros.CreateDerivedEnumerationCodec.scala Maven / Gradle / Ivy

There is a newer version: 1.11.9
Show newest version
package sttp.tapir.macros

import sttp.tapir.Codec.PlainCodec
import sttp.tapir.{Codec, DecodeResult, SchemaAnnotations, ValidationError, Validator}

class CreateDerivedEnumerationCodec[L, T](validator: Validator.Enumeration[T], schemaAnnotations: SchemaAnnotations[T]) {

  // needed for binary compatibility
  def this(validator: Validator.Enumeration[T]) = this(validator, SchemaAnnotations.empty)

  /** Creates the codec using the provided decoding & encoding functions.
    *
    * @param decode
    *   How low-level values are decoded to the enum value. `None` if the low-level value is invalid, that is, when there's no high-level
    *   enum value.
    * @param encode
    *   How the enum value is encoded as a low-level value.
    */
  def apply(
      decode: L => Option[T],
      encode: T => L,
      default: Option[T] = None
  )(implicit baseCodec: PlainCodec[L]): PlainCodec[T] = {
    val v = validator.encode(encode)

    val s0 = baseCodec.schema.map(decode)(encode).validate(v)
    val s = default.fold(s0)(d => s0.default(d, Some(encode(d))))

    baseCodec
      .mapDecode(s =>
        decode(s) match {
          case Some(value) => DecodeResult.Value(value)
          case None        => DecodeResult.InvalidValue(List(ValidationError(validator, s)))
        }
      )(encode)
      .schema(schemaAnnotations.enrich(s))
  }

  /** Creates the codec assuming the low-level representation is a `String`. The encoding function uses the enum's `.toString`. Similarly,
    * the decoding function performs a case-insensitive search using the enum's `.toString`
    */
  def defaultStringBased(implicit lIsString: L =:= String): PlainCodec[T] =
    apply(
      s => validator.possibleValues.find(_.toString.equalsIgnoreCase(s.asInstanceOf[String])), // we know that L == String
      _.toString.asInstanceOf[L],
      None
    )(Codec.string.asInstanceOf[PlainCodec[L]])
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy