Skip to content

Commit

Permalink
Add Mapping.Inject and .Project
Browse files Browse the repository at this point in the history
  • Loading branch information
taig committed Jul 7, 2024
1 parent 79a3421 commit 7fc2c7a
Showing 1 changed file with 48 additions and 5 deletions.
53 changes: 48 additions & 5 deletions modules/core/src/main/scala/io/taig/enumeration/ext/Mapping.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,54 @@ import cats.data.NonEmptyMap
import scala.annotation.targetName
import cats.Order

sealed abstract class Mapping[A, B] extends Inject[A, B]:
def values: List[A]
sealed abstract class Mapping[A, B] extends Inject[A, B], Mapping.Inject[A, B], Mapping.Project[A, B]

object Mapping:
sealed trait Inject[A, B]:
def values: List[A]

def inj: A => B

object Inject:
inline def apply[A, B](using mapping: Mapping.Inject[A, B]): Mapping.Inject[A, B] = mapping

def enumeration[A, B: Order](f: A => B)(using values: EnumerationValues.Aux[A, A]): Mapping.Inject[A, B] =
new Mapping.Inject[A, B]:
override def values: List[A] = valuesOf[A].toList
override def inj: A => B = f

def constant[A <: B: ValueOf, B: Eq]: Mapping.Inject[A, B] = new Mapping.Inject[A, B]:
override def values: List[A] = List(valueOf[A])
override def inj: A => B = identity

@targetName("constantOf")
def constant[A: Eq](value: A & Singleton): Mapping.Inject[value.type, A] = constant[value.type, A]

sealed trait Project[A, B]:
def values: List[A]

def prj: B => Option[A]

object Project:
inline def apply[A, B](using mapping: Mapping.Project[A, B]): Mapping.Project[A, B] = mapping

def enumeration[A, B: Order](f: A => B)(using values: EnumerationValues.Aux[A, A]): Mapping.Project[A, B] =
new Mapping.Project[A, B]:
val valuesNel = valuesOf[A]
val lookup: NonEmptyMap[B, A] =
NonEmptyMap.of((f(valuesNel.head), valuesNel.head), valuesNel.tail.map(a => (f(a), a))*)

override def values: List[A] = valuesNel.toList
override def prj: B => Option[A] = lookup.apply

def constant[A <: B: ValueOf, B: Eq]: Mapping.Project[A, B] = new Mapping.Project[A, B]:
val a: A = valueOf[A]
override def values: List[A] = List(a)
override def prj: B => Option[A] = b => Option.when(b === a)(a)

@targetName("constantOf")
def constant[A: Eq](value: A & Singleton): Mapping.Project[value.type, A] = constant[value.type, A]

inline def apply[A, B](using mapping: Mapping[A, B]): Mapping[A, B] = mapping

def enumeration[A, B: Order](f: A => B)(using values: EnumerationValues.Aux[A, A]): Mapping[A, B] = new Mapping[A, B]:
Expand All @@ -23,10 +67,9 @@ object Mapping:
override def prj: B => Option[A] = lookup.apply

def constant[A <: B: ValueOf, B: Eq]: Mapping[A, B] = new Mapping[A, B]:
val a: A = valueOf[A]
override def values: List[A] = List(a)
override def values: List[A] = List(valueOf[A])
override def inj: A => B = identity
override def prj: B => Option[A] = b => Option.when(b === a)(a)
override def prj: B => Option[A] = b => Option.when(b === valueOf[A])(valueOf[A])

@targetName("constantOf")
def constant[A: Eq](value: A & Singleton): Mapping[value.type, A] = constant[value.type, A]

0 comments on commit 7fc2c7a

Please sign in to comment.