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

io.github.arainko.ducktape.internal.FallibilityRefiner.scala Maven / Gradle / Ivy

The newest version!
package io.github.arainko.ducktape.internal

import io.github.arainko.ducktape.internal.Plan.*
import io.github.arainko.ducktape.internal.Summoner.Derived.{ FallibleTransformer, TotalTransformer }
import io.github.arainko.ducktape.internal.Summoner.UserDefined.{ FallibleTransformer, TotalTransformer }

import scala.util.boundary
import scala.util.boundary.Label

private[ducktape] object FallibilityRefiner {
  def run[E <: Erroneous](plan: Plan[E, Fallible]): Plan[E, Nothing] | None.type =
    recurse(plan) match
      case None    => None
      case b: Unit => plan.asInstanceOf[Plan[E, Nothing]]

  private def recurse[E <: Erroneous](plan: Plan[E, Fallible]): None.type | Unit =
    boundary[None.type | Unit]:
      plan match
        case Upcast(source, dest, _) => ()

        case UserDefined(source, dest, transformer) =>
          transformer match
            case Summoner.UserDefined.TotalTransformer(value)    => ()
            case Summoner.UserDefined.FallibleTransformer(value) => boundary.break(None)

        case Derived(source, dest, transformer) =>
          transformer match
            case Summoner.Derived.TotalTransformer(value)    => ()
            case Summoner.Derived.FallibleTransformer(value) => boundary.break(None)

        case Configured(source, dest, config, _) =>
          config match
            case Configuration.Const(value, tpe)                    => ()
            case Configuration.CaseComputed(tpe, function)          => ()
            case Configuration.FieldComputed(tpe, function)         => ()
            case Configuration.FieldReplacement(source, name, tpe)  => ()
            case Configuration.FallibleConst(value, tpe)            => boundary.break(None)
            case Configuration.FallibleFieldComputed(tpe, function) => boundary.break(None)
            case Configuration.FallibleCaseComputed(tpe, function)  => boundary.break(None)

        case BetweenProductFunction(source, dest, argPlans) =>
          evaluate(argPlans.values)

        case BetweenTupleFunction(source, dest, argPlans) =>
          evaluate(argPlans.values)

        case BetweenUnwrappedWrapped(source, dest) => ()

        case BetweenWrappedUnwrapped(source, dest, fieldName) => ()

        case BetweenSingletons(source, dest) => ()

        case BetweenProducts(source, dest, fieldPlans) =>
          evaluate(fieldPlans.values)

        case BetweenProductTuple(source, dest, plans) =>
          evaluate(plans)

        case BetweenTupleProduct(source, dest, plans) =>
          evaluate(plans.values)

        case BetweenTuples(source, dest, plans) =>
          evaluate(plans)

        case BetweenCoproducts(source, dest, casePlans) =>
          evaluate(casePlans)

        case BetweenOptions(source, dest, plan) =>
          recurse(plan)

        case BetweenNonOptionOption(source, dest, plan) =>
          recurse(plan)

        case BetweenCollections(source, dest, _, plan) =>
          recurse(plan)

        case BetweenFallibleNonFallible(source, dest, plan) =>
          boundary.break(None)

        case BetweenFallibles(_, _, _, _) =>
          boundary.break(None)

        case Plan.Error(source, dest, message, suppressed) => ()

  private inline def evaluate(plans: Iterable[Plan[Erroneous, Fallible]])(using inline label: boundary.Label[None.type | Unit]) =
    val iterator = plans.iterator
    while iterator.hasNext do
      recurse(iterator.next()) match {
        case None => boundary.break(None)
        case ()   => ()
      }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy