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

scala.pickling.internal.package.scala Maven / Gradle / Ivy

The newest version!
package scala.pickling

import java.util.concurrent.atomic.AtomicReference

import scala.language.experimental.macros
import scala.language.reflectiveCalls

import java.util.IdentityHashMap

import HasCompat._

package object internal {

  import scala.reflect.runtime.{universe => ru}
  import ru._
  import compat._

  private[this] def initDefaultRuntime = {
    // TODO - Figure out a better way to configure this.... (typesafe config?)
    sys.props.getOrElse("pickling.runtime", "default") match {
      case "hybrid" => new HybridRuntime()
      case "noreflection" => new NoReflectionRuntime()
      case _ => new DefaultRuntime()

    }
  }
  private[this] var currentRuntimeVar = new AtomicReference[spi.PicklingRuntime](initDefaultRuntime)
  def currentRuntime: spi.PicklingRuntime = currentRuntimeVar.get
  // Here we inject a new runtime for usage.
  def replaceRuntime(r: spi.PicklingRuntime): Unit = {
    currentRuntimeVar.lazySet(r)
  }

  /* Global reflection lock.
   * It is used to avoid data races that typically lead to runtime exceptions
   * when using (Scala) runtime reflection on Scala 2.10.x.
   *
   * Note: visibility must be public, so that the lock can be accessed from
   *       macro-generated code.
   */
  def GRL = currentRuntime.GRL

  // TOGGLE DEBUGGING
  private val debugEnabled: Boolean = System.getProperty("pickling.debug", "false").toBoolean
  private[pickling] def debug(output: => String) = if (debugEnabled) println(output)


  // ----- internal extension methods for symbols -----
  private[pickling] implicit class RichSymbol(sym: scala.reflect.api.Universe#Symbol) {
    def isEffectivelyFinal = sym.asInstanceOf[scala.reflect.internal.Symbols#Symbol].isEffectivelyFinal
    def isEffectivelyPrimitive = throw new Exception("use Type.isEffectivelyPrimitive instead")
    def isNotNullable = sym.isClass && (sym.asClass.isPrimitive || sym.asClass.isDerivedValueClass)
    def isNullable = sym.isClass && !isNotNullable
  }
  def currentMirror: ru.Mirror = currentRuntime.currentMirror

  private[pickling] def typeToString(tpe: Type): String = tpe.key

  private val typeFromStringCache = scala.collection.concurrent.TrieMap[String, Type]()
  private[pickling] def typeFromString(mirror: Mirror, stpe: String): Type = {
    // TODO: find out why typeFromString is called repeatedly for scala.Predef.String (at least in the evactor1 bench)
    if (typeFromStringCache.contains(stpe)) typeFromStringCache(stpe)
    else {
      val result =
        AppliedType.parseFull(stpe) match {
          case Some(AppliedType(typename, appliedTypeArgs)) =>
            def errorMsg = s"""error: cannot find class or module with type name '$typename'
                              |full type string: '$stpe'""".stripMargin

            val sym = try {
              if (typename.endsWith(".type")) mirror.staticModule(typename.stripSuffix(".type")).moduleClass
              else mirror.staticClass(typename)
            } catch {
              case _: ScalaReflectionException =>
                sys.error(errorMsg)
              case _: scala.reflect.internal.MissingRequirementError =>
                sys.error(errorMsg)
            }
            val tycon = sym.asType.toTypeConstructor
            appliedType(tycon, appliedTypeArgs.map(starg => typeFromString(mirror, starg.toString)))
          case None =>
            sys.error(s"fatal: cannot unpickle $stpe")
        }
      typeFromStringCache(stpe) = result
      result
    }
  }

  // FIXME: duplication wrt Tools, but I don't really fancy abstracting away this path-dependent madness
  private[pickling] implicit class RichTypeFIXME(tpe: Type) {
    import definitions._
    def key: String = {
      tpe.normalize match {
        case ExistentialType(tparams, TypeRef(pre, sym, targs))
        if targs.nonEmpty && targs.forall(targ => tparams.contains(targ.typeSymbol)) =>
          TypeRef(pre, sym, Nil).key
        case TypeRef(pre, sym, targs) if pre.typeSymbol.isModuleClass =>
          sym.fullName +
          (if (sym.isModuleClass) ".type" else "") +
          (if (targs.isEmpty) "" else targs.map(_.key).mkString("[", ",", "]"))
        case _ =>
          tpe.toString
      }
    }
    def isEffectivelyPrimitive: Boolean = tpe match {
      case TypeRef(_, sym: ClassSymbol, _) if sym.isPrimitive => true
      case TypeRef(_, sym, eltpe :: Nil) if sym == ArrayClass && eltpe.typeSymbol.isClass && eltpe.typeSymbol.asClass.isPrimitive => true
      case _ => false
    }
  }


  // ----- utilities for managing object identity -----
  @deprecated("Use `currentRuntime.refRegistry.pickle.registerPicklee` instead", "0.11")
  def lookupPicklee(picklee: Any): Int = currentRuntime.refRegistry.pickle.registerPicklee(picklee)
  @deprecated("Use `currentRuntime.refRegistry.pickle.registerPicklee` instead", "0.11")
  def registerPicklee(picklee: Any): Int = currentRuntime.refRegistry.pickle.registerPicklee(picklee)
  @deprecated("Use `currentRuntime.refRegistry.pickle.clear` instead", "0.11")
  def clearPicklees() = currentRuntime.refRegistry.pickle.clear()
  @deprecated("Use `currentRuntime.refRegistry.unpickle.lookupUnpicklees` instead", "0.11")
  def lookupUnpicklee(index: Int): Any = currentRuntime.refRegistry.unpickle.lookupUnpicklee(index)
  @deprecated("Use `currentRuntime.refRegistry.unpickle.preregisterUnpicklee` instead", "0.11")
  def preregisterUnpicklee() = currentRuntime.refRegistry.unpickle.preregisterUnpicklee()
  @deprecated("Use `currentRuntime.refRegistry.unpickle.registerUnpicklee` instead", "0.11")
  def registerUnpicklee(unpicklee: Any, index: Int) = currentRuntime.refRegistry.unpickle.regsiterUnpicklee(index, unpicklee)
  @deprecated("Use `currentRuntime.refRegistry.unpickle.clear` instead", "0.11")
  def clearUnpicklees() = currentRuntime.refRegistry.unpickle.clear()
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy