Skip to content

Commit 00b7cf5

Browse files
committed
add-scaal3-enum-put-get-derivation
1 parent 23623fe commit 00b7cf5

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

modules/core/src/main/scala-3/doobie/util/GetPlatform.scala

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,22 @@
44

55
package doobie.util
66

7-
trait GetPlatform {}
7+
import scala.deriving.Mirror
8+
import scala.compiletime.constValue
9+
10+
trait GetPlatform {
11+
private def of[A](name: String, cases: List[A], labels: List[String]): Get[A] =
12+
Get[String].temap { caseName =>
13+
labels.indexOf(caseName) match {
14+
case -1 => Left(s"enum $name does not contain case: $caseName")
15+
case i => Right(cases(i))
16+
}
17+
}
18+
19+
inline final def deriveEnumString[A](using mirror: Mirror.SumOf[A]): Get[A] =
20+
of(
21+
constValue[mirror.MirroredLabel],
22+
summonSingletonCases[mirror.MirroredElemTypes, A](constValue[mirror.MirroredLabel]),
23+
summonLabels[mirror.MirroredElemLabels]
24+
)
25+
}

modules/core/src/main/scala-3/doobie/util/PutPlatform.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,13 @@
44

55
package doobie.util
66

7-
trait PutPlatform
7+
import scala.compiletime.constValue
8+
import scala.deriving.Mirror
9+
10+
trait PutPlatform {
11+
inline final def deriveEnumString[A](using mirror: Mirror.SumOf[A]): Put[A] =
12+
val _ = summonSingletonCases[mirror.MirroredElemTypes, A](constValue[mirror.MirroredLabel])
13+
val labels = summonLabels[mirror.MirroredElemLabels]
14+
15+
Put[String].contramap(a => labels(mirror.ordinal(a)))
16+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (c) 2013-2020 Rob Norris and Contributors
2+
// This software is licensed under the MIT License (MIT).
3+
// For more information see LICENSE or https://opensource.org/licenses/MIT
4+
5+
package doobie.util
6+
7+
import scala.compiletime.{codeOf, constValue, erasedValue, error, summonInline}
8+
import scala.deriving.Mirror
9+
10+
private[util] inline final def summonLabels[T <: Tuple]: List[String] =
11+
inline erasedValue[T] match
12+
case _: EmptyTuple => Nil
13+
case _: (t *: ts) => constValue[t].asInstanceOf[String] :: summonLabels[ts]
14+
15+
private[util] inline final def summonSingletonCases[T <: Tuple, A](inline typeName: Any): List[A] =
16+
inline erasedValue[T] match
17+
case _: EmptyTuple => Nil
18+
case _: (h *: t) =>
19+
inline summonInline[Mirror.Of[h]] match
20+
case m: Mirror.Singleton => m.fromProduct(EmptyTuple).asInstanceOf[A] :: summonSingletonCases[t, A](typeName)
21+
case m: Mirror =>
22+
error("Enum " + codeOf(typeName) + " contains non singleton case " + codeOf(constValue[m.MirroredLabel]))

0 commit comments

Comments
 (0)