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

scala.pickling.generator.algorithms.scala Maven / Gradle / Ivy

The newest version!
package scala.pickling
package generator

import scala.reflect.api.Universe

/** An interface so we can pass logging to these algorithms at runtime/during testing. */
private[pickling] trait AlgorithmLogger {
  def warn(msg: String): Unit
  def debug(msg: String): Unit
  def error(msg: String): Unit
  def abort(msg: String): Nothing
}

/** Represents the result of an algorithm call. */
private[pickling]sealed trait AlgorithmResult {
  def join(other: => AlgorithmResult): AlgorithmResult
  def map(f: PickleUnpickleImplementation => PickleUnpickleImplementation): AlgorithmResult =
     this match {
       case AlgorithmSucccess(i) => AlgorithmSucccess(f(i))
       case x => x
     }
}
private[pickling]final case class AlgorithmSucccess(impl: PickleUnpickleImplementation) extends AlgorithmResult {
  def join(other: => AlgorithmResult): AlgorithmResult = this
}
/** A list of reasons why an algorithm failued to run. */
private[pickling]final case class AlgorithmFailure(reasons: List[String]) extends AlgorithmResult {
  def join(other: => AlgorithmResult): AlgorithmResult =
    other match {
      case x: AlgorithmSucccess => x
      case AlgorithmFailure(rs) => AlgorithmFailure(reasons ++ rs)
    }
}
private[pickling]object AlgorithmFailure {
  def apply(reason: String): AlgorithmFailure = AlgorithmFailure(List(reason))
}
/** An algorithm whcih can generate the IR of a pickler/unpickler *OR* a  good set of error messages. */
private[pickling] trait PicklingAlgorithm {
  /**
   * Attempts to construct pickling logic for a given type.
   */
  def generate(tpe: IrClass, logger: AlgorithmLogger): AlgorithmResult
}
private[pickling] object PicklingAlgorithm {
  def run(alg: PicklingAlgorithm)(tpe: IrClass, logger: AlgorithmLogger): Option[PickleUnpickleImplementation] = {
    alg.generate(tpe, logger) match {
      case AlgorithmSucccess(success) => Some(success)
      case AlgorithmFailure(failures) =>
        val fString = failures.mkString("\n - ", "\n - ", "\n")
        logger.error(s"Unable to generate pickling/unpickling implementation for $tpe.\n$fString")
        None
    }
  }


  /** Aggregates the sequence of picklers (prioritizing left-to-right or first-to-last) to
    * create a new "uber" pickling algorithm.
    * @param algs
    *             The list of pickling algorithms to try, in-order.
    * @return
    *         A new algorithm which will try all passed in algorithms and only fail if all algorithms fail.
    */
  def aggregate(algs: Seq[PicklingAlgorithm]): PicklingAlgorithm =
     new PicklingAlgorithm {
       /**
        * Attempts to construct pickling logic for a given type.
        */
       override def generate(tpe: IrClass, logger: AlgorithmLogger): AlgorithmResult =
         algs.foldLeft(AlgorithmFailure(List()): AlgorithmResult) { (prev, next) =>
           prev match {
             case x: AlgorithmSucccess => x
             case y: AlgorithmFailure =>
               //logger.debug(s"Trying algorithm: $next on $tpe")
               y join next.generate(tpe, logger)
           }
         }
     }
}


// TODO - Java Serializable Serializer
// TODO - Java Bean serializer
// TODO - Crazy-Kryo-like-serializer





© 2015 - 2025 Weber Informatics LLC | Privacy Policy