Skip to content

Commit

Permalink
Merge 83fd2f6 into cd800d5
Browse files Browse the repository at this point in the history
  • Loading branch information
ruippeixotog committed Oct 1, 2023
2 parents cd800d5 + 83fd2f6 commit 9a20849
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 46 deletions.
Expand Up @@ -2,6 +2,7 @@ package pureconfig
package generic
package derivation

import scala.compiletime.summonFrom
import scala.deriving.Mirror

trait ConfigReaderDerivation extends CoproductConfigReaderDerivation with ProductConfigReaderDerivation {
Expand All @@ -12,6 +13,15 @@ trait ConfigReaderDerivation extends CoproductConfigReaderDerivation with Produc
case given Mirror.SumOf[A] => derivedSum
}
}

/** Summons a `ConfigReader` for a given type `A`. It first tries to find an existing given instance of
* `ConfigReader[A]`. If none is found, it tries to derive one using this `ConfigReaderDerivation` instance. This
* method differs from `derived` in that the latter doesn't try to find an existing instance first.
*/
protected inline def summonConfigReader[A] = summonFrom {
case reader: ConfigReader[A] => reader
case given Mirror.Of[A] => ConfigReader.derived[A]
}
}

object ConfigReaderDerivation {
Expand Down
Expand Up @@ -7,7 +7,7 @@ import scala.deriving.Mirror

import pureconfig.error.{CannotConvert, ConfigReaderFailures}
import pureconfig.generic.derivation.ConfigReaderDerivation
import pureconfig.generic.derivation.WidenType.widen
import pureconfig.generic.derivation.Utils._

trait CoproductConfigReaderDerivation(fieldMapping: ConfigFieldMapping, optionField: String) {
self: ConfigReaderDerivation =>
Expand All @@ -33,8 +33,7 @@ trait CoproductConfigReaderDerivation(fieldMapping: ConfigFieldMapping, optionFi
} yield result

val readers =
Labels
.transformed[m.MirroredElemLabels](fieldMapping)
transformedLabels[A](fieldMapping)
.zip(deriveForSubtypes[m.MirroredElemTypes, A])
.toMap
}
Expand All @@ -46,11 +45,5 @@ trait CoproductConfigReaderDerivation(fieldMapping: ConfigFieldMapping, optionFi
}

inline def deriveForSubtype[A0, A]: ConfigReader[A] =
summonFrom {
case reader: ConfigReader[A0] =>
reader.map(widen[A0, A](_))

case given Mirror.Of[A0] =>
ConfigReader.derived[A0].map(widen[A0, A](_))
}
summonConfigReader[A0].map(widen[A0, A](_))
}
Expand Up @@ -6,7 +6,7 @@ import scala.compiletime.{constValue, erasedValue, error, summonInline}
import scala.deriving.Mirror

import pureconfig.error.{CannotConvert, ConfigReaderFailures}
import pureconfig.generic.derivation.WidenType.widen
import pureconfig.generic.derivation.Utils._

type EnumConfigReader[A] = EnumConfigReaderDerivation.Default.EnumConfigReader[A]

Expand Down Expand Up @@ -53,7 +53,7 @@ trait EnumConfigReaderDerivation(transformName: String => String) {
inline transformName: String => String,
inline value: String
)(using m: Mirror.SumOf[A]) = {
val ord = Labels.transformed[m.MirroredElemLabels](transformName).indexOf(value)
val ord = transformedLabels[A](transformName).indexOf(value)
Option.when(ord >= 0)(ord)
}
}
Expand Down
17 changes: 0 additions & 17 deletions core/src/main/scala-3/pureconfig/generic/derivation/Labels.scala

This file was deleted.

Expand Up @@ -8,7 +8,7 @@ import scala.deriving.Mirror
import scala.util.chaining.*

import pureconfig.error.{ConfigReaderFailures, ConvertFailure, KeyNotFound, UnknownKey, WrongSizeList}
import pureconfig.generic.derivation.WidenType.widen
import pureconfig.generic.derivation.Utils._

trait ProductConfigReaderDerivation(fieldMapping: ConfigFieldMapping) { self: ConfigReaderDerivation =>
inline def derivedProduct[A](using m: Mirror.ProductOf[A]): ConfigReader[A] =
Expand Down Expand Up @@ -38,8 +38,7 @@ trait ProductConfigReaderDerivation(fieldMapping: ConfigFieldMapping) { self: Co
for {
objCur <- cur.asObjectCursor
result <-
Labels
.transformed[m.MirroredElemLabels](fieldMapping)
transformedLabels[A](fieldMapping)
.pipe(labels =>
readTuple[m.MirroredElemTypes, 0](
labels.map(objCur.atKeyOrUndefined(_)),
Expand Down Expand Up @@ -74,10 +73,4 @@ trait ProductConfigReaderDerivation(fieldMapping: ConfigFieldMapping) { self: Co
case _: EmptyTuple =>
Right(widen[EmptyTuple, T](EmptyTuple))
}

inline def summonConfigReader[A] =
summonFrom {
case reader: ConfigReader[A] => reader
case given Mirror.Of[A] => ConfigReader.derived[A]
}
}
35 changes: 35 additions & 0 deletions core/src/main/scala-3/pureconfig/generic/derivation/Utils.scala
@@ -0,0 +1,35 @@
package pureconfig.generic
package derivation

import scala.compiletime.{constValue, erasedValue, summonFrom, summonInline}
import scala.deriving.Mirror

object Utils {

/** Asserts in compile time that a given value of type `A` is also of type `B`.
*
* @param a
* the value whose type to assert
* @return
* `a` with a widened type.
*/
inline def widen[A, B](a: A): A & B =
inline a match { case b: B => b }

/** Materializes the labels of a `A` (e.g. product element names, coproduct options) as a list of strings with an
* optional compile-time transformation. The function is guaranteed to return a constant list.
*
* @param transform
* the function to transform keys with
* @return
* the list of transformed labels.
*/
inline def transformedLabels[A](inline transform: String => String)(using m: Mirror.Of[A]): List[String] =
transformedLabelsTuple[m.MirroredElemLabels](transform)

private inline def transformedLabelsTuple[T <: Tuple](inline transform: String => String): List[String] =
inline erasedValue[T] match {
case _: (h *: t) => transform(constValue[h & String]) :: transformedLabelsTuple[t](transform)
case _: EmptyTuple => Nil
}
}

This file was deleted.

0 comments on commit 9a20849

Please sign in to comment.