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

scala.pickling.Pickler.scala Maven / Gradle / Ivy

The newest version!
package scala.pickling

import scala.language.experimental.macros
import scala.language.implicitConversions

import scala.annotation.implicitNotFound
import scala.pickling.internal._

/** A static pickler for type `T`. Its `pickle` method takes an object-to-be-pickled of
 *  static type `T`, and pickles it to an instance of `PBuilder`. In the process the object
 *  is turned into some external representation like a byte array. The particular external
 *  representation (the "pickle format") is defined by the `builder`.
 *
 *  This pickler requires that the dynamic type of the object-to-be-pickled is equal to
 *  the erasure of its static type `T`.
 */
@implicitNotFound(msg = "Cannot generate a pickler for ${T}. Recompile with -Xlog-implicits for details")
trait Pickler[T] {
  /** Uses the given builder to place 'primitive' values, or collections/structures, into the
   *  builder.
   */
  def pickle(picklee: T, builder: PBuilder): Unit
  /** The fast type tag associated with this pickler. */
  def tag: FastTypeTag[T]
}
// Shim for Java code.
abstract class AbstractPickler[T] extends Pickler[T]
object Pickler {
  def generate[T]: Pickler[T] = macro generator.Compat.genPickler_impl[T]
}

/** A dynamic pickler for type `T`. Its `pickle` method takes an object-to-be-pickled of
 *  static type `T`, and pickles it to an instance of `PBuilder`. In the process the object
 *  is turned into some external representation like a byte array. The particular external
 *  representation (the "pickle format") is defined by the `builder`.
 *
 *  In contrast to static picklers (instances of type `Pickler[T]`), a dynamic pickler of
 *  type `DPickler[T]` pickles any object of type `T`.
 */
@implicitNotFound(msg = "Cannot generate a DPickler for ${T}. Recompile with -Xlog-implicits for details")
trait DPickler[T] {
  def pickle(picklee: T, builder: PBuilder): Unit
}
// marker trait to indicate a generated pickler
// this is important for the dispatch between custom and generated picklers
trait Generated

/** This is something which knowns how to reconstitute/materialize a type out of
 *  a pickle reader.
 */
@implicitNotFound(msg = "Cannot generate an unpickler for ${T}. Recompile with -Xlog-implicits for details")
trait Unpickler[T] {
  // TODO - we'd like  to call this method unpickeRaw and the unpickleEntry method `unpickle`,
  //        as there is some logic about how to use the reader encoded here.
  /** Unpickles an entry out of hte reader.
   *  
   *  note:  This method ASSUMES beginEntry() has already been called and endEntry() will be
   *         called immediately afterwards.
   *
   * @param tag  The FastTypeTag[_].key that was serialized with the entry *or* the type hint
   *             which was provided when reading.  This is generally used by abstract type 
   *             Unpicklers to delegate to the appropriate concrete unpickler.
   * @param reader  The reader we can grab fields, primitives or collection items out of.
   * @return Any an instance of the type we've unpickled.
   */
  def unpickle(tag: String, reader: PReader): Any
  /** A mechanism of unpickling that also includes calling beginEntry()/endEntry(). 
   *  Note: We assume anyone calling this will hint "staticallyElided" or "dynamicallyElided"
   *        if needed.   Each Unpickler should make no assumptions about its own type.
   */
  def unpickleEntry(reader: PReader): Any = {
    // TODO - If we are statically elided, we should HINT our type.
    val tag = reader.beginEntry()
    val result = unpickle(tag, reader)
    reader.endEntry()
    result
  }
  /** The fast type tag associated with this unpickler. */
  def tag: FastTypeTag[T]
}
// Shim for Java code.
abstract class AbstractUnpickler[T] extends Unpickler[T]
object Unpickler {
  def generate[T]: Unpickler[T] = macro generator.Compat.genUnpickler_impl[T]
}
/* Shim for java code which wants to pickle/unpickle. */
abstract class AbstractPicklerUnpickler[T] extends Pickler[T] with Unpickler[T]
object PicklerUnpickler {
  def apply[T](p: Pickler[T], u: Unpickler[T]): AbstractPicklerUnpickler[T] = new DelegatingPicklerUnpickler(p, u)
  //def generate[T]: Pickler[T] with Unpickler[T] = macro Compat.PicklerUnpicklerMacros_impl[T]
  def generate[T]: AbstractPicklerUnpickler[T] = macro generator.Compat.genPicklerUnpickler_impl[T]
  /** This is a private implementation of PicklerUnpickler that delegates pickle and unpickle to underlying. */
  private class DelegatingPicklerUnpickler[T](p: Pickler[T], u: Unpickler[T]) extends AbstractPicklerUnpickler[T] {
    // From Pickler
    override def pickle(picklee: T, builder: PBuilder): Unit = p.pickle(picklee, builder)
    // From Pickler and Unpickler
    override def tag: FastTypeTag[T] = p.tag
    // From Unpickler
    override def unpickle(tag: String, reader: PReader): Any = u.unpickle(tag, reader)
  }
}

/** A pickler which will register itself with the runtime pickler registery. */
abstract class AutoRegister[T: FastTypeTag](name: String) extends AbstractPicklerUnpickler[T] {
  val tag = implicitly[FastTypeTag[T]]

  // Register this pickler with the global handler.
  locally {
    val p = internal.currentRuntime.picklers
    debug(s"autoregistering pickler $this under key '${tag.key}'")
    p.registerPickler(tag.key, this)
    debug(s"autoregistering unpickler $this under key '${tag.key}'")
    p.registerUnpickler(tag.key, this)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy