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

sbt.incremental-compiler.0.13.1.source-code.generic.scala Maven / Gradle / Ivy

There is a newer version: 0.13.15
Show newest version
/**
 * Generic operations for building binary instances.
 */
package sbinary;

import scala.collection.mutable.{ListBuffer, ArrayBuffer};
import scala.collection._;

import java.io._;
import Operations._;

trait Generic extends CoreProtocol{
  implicit def arrayFormat[T](implicit fmt : Format[T], mf: scala.reflect.Manifest[T]) : Format[Array[T]];
  // Needed to implement viaSeq
  implicit def listFormat[T](implicit fmt : Format[T]) : Format[List[T]];

  /** A more general LengthEncoded (arrays are no longer collections) */
  abstract class CollectionFormat[S, T](implicit binT : Format[T]) extends Format[S]{
    def size(s: S): Int
    def foreach(s: S)(f: T => Unit): Unit
    def build(size : Int, ts : Iterator[T]) : S;

    def reads(in : Input) = { val size = read[Int](in); build(size, (0 until size).map(i => read[T](in)).iterator) }
    def writes(out : Output, ts : S) = { write(out, size(ts)); foreach(ts)(write(out, _)); }
  }
  /** 
   * Format instance which encodes the collection by first writing the length
   * of the collection as an int, then writing the collection elements in order.
   */
  abstract class LengthEncoded[S <: Traversable[T], T](implicit binT : Format[T]) extends CollectionFormat[S, T]{
    def size(s: S) = s.size
    def foreach(s: S)(f: T => Unit) = s.foreach(f)
  }

  /**
   * Length encodes, but with the result built from an array.
   */
  def viaArray[S <: Traversable[T], T] (f : Array[T] => S) (implicit binary : Format[T], mf: scala.reflect.Manifest[T]) : Format[S] = new Format[S] {
    def writes(out : Output, xs : S) = { write(out, xs.size); xs.foreach(write(out, _)); }
    def reads(in : Input) = f(read[Array[T]](in));
  }
  /**
   * Length encodes, but with the result built from a Seq.
	* Useful for when a `ClassManifest` is not available the underlying type `T`.
   */
  def viaSeq[S <: Traversable[T], T] (f : Seq[T] => S) (implicit binary : Format[T]) : Format[S] = new Format[S] {
    def writes(out : Output, xs : S) = { write(out, xs.size); xs.foreach(write(out, _)); }
    def reads(in : Input) = f(read[List[T]](in));
  }

  /**
   * Encodes and decodes via some String representation.
   */
  def viaString[T](f : String => T) = new Format[T]{
    def reads(in : Input) = f(read[String](in));
    def writes(out : Output, t : T) = write(out, t.toString);
  }
  
  /**
   * Trivial serialization. Writing is a no-op, reading always returns this instance.
   */
  def asSingleton[T](t : T) : Format[T] = new Format[T]{
    def reads(in : Input) = t
    def writes(out : Output, t : T) = ();
  }

  /**
   * Serializes this via a bijection to some other type. 
   */
  def wrap[S, T](to : S => T, from : T => S)(implicit bin : Format[T]) = new Format[S]{
    def reads(in : Input) = from(read[T](in));
    def writes(out : Output, s : S) = write(out, to(s));
  }

  /**
   * Lazy wrapper around a binary. Useful when you want e.g. mutually recursive binary instances.
   */
  def lazyFormat[S](bin : =>Format[S]) = new Format[S]{
    lazy val delegate = bin;

    def reads(in : Input) = delegate.reads(in);
    def writes(out : Output, s : S) = delegate.writes(out, s);
  }

  /**
   * Attaches a stamp to the data. This stamp is placed at the beginning of the format and may be used
   * to verify the integrity of the data (e.g. a magic number for the data format version). 
   */
  def withStamp[S, T](stamp : S)(binary : Format[T])(implicit binS : Format[S]) : Format[T] = new Format[T]{
    def reads(in : Input) = {
      val datastamp = read[S](in);
      if (stamp != datastamp) error("Incorrect stamp. Expected: " + stamp + ", Found: " + datastamp);
      binary.reads(in);
    }

    def writes(out : Output, t : T) = {
      write(out, stamp);
      binary.writes(out, t);
    }
  }

  /**
   * Create a format for an enumeration, representing values by their integer IDs.
   *
   * Note that due to type system limitations we cannot enforce that you pass the right Enumeration to this method.
   * Be good.
   */
  def enumerationFormat[V <: Enumeration#Value](enumeration : Enumeration) = new Format[V]{
    def reads(in : Input) = enumeration(read[Int](in)).asInstanceOf[V]
    def writes(out : Output, value : V) = write(out, value.id)
  }

    /**
   * Represents this type as 2 consecutive binary blocks of type T1..T2,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct2[S, T1,T2](apply : (T1,T2) => S)(unapply : S => Product2[T1,T2])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
        ;       
      }
    }  
  /**
   * Represents this type as 3 consecutive binary blocks of type T1..T3,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct3[S, T1,T2,T3](apply : (T1,T2,T3) => S)(unapply : S => Product3[T1,T2,T3])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
        ;       
      }
    }  
  /**
   * Represents this type as 4 consecutive binary blocks of type T1..T4,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct4[S, T1,T2,T3,T4](apply : (T1,T2,T3,T4) => S)(unapply : S => Product4[T1,T2,T3,T4])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
        ;       
      }
    }  
  /**
   * Represents this type as 5 consecutive binary blocks of type T1..T5,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct5[S, T1,T2,T3,T4,T5](apply : (T1,T2,T3,T4,T5) => S)(unapply : S => Product5[T1,T2,T3,T4,T5])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] ,
          bin5 : Format[T5] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in),
         read[T5](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
                  write(out, product._5);
        ;       
      }
    }  
  /**
   * Represents this type as 6 consecutive binary blocks of type T1..T6,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct6[S, T1,T2,T3,T4,T5,T6](apply : (T1,T2,T3,T4,T5,T6) => S)(unapply : S => Product6[T1,T2,T3,T4,T5,T6])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] ,
          bin5 : Format[T5] ,
          bin6 : Format[T6] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in),
         read[T5](in),
         read[T6](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
                  write(out, product._5);
                  write(out, product._6);
        ;       
      }
    }  
  /**
   * Represents this type as 7 consecutive binary blocks of type T1..T7,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct7[S, T1,T2,T3,T4,T5,T6,T7](apply : (T1,T2,T3,T4,T5,T6,T7) => S)(unapply : S => Product7[T1,T2,T3,T4,T5,T6,T7])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] ,
          bin5 : Format[T5] ,
          bin6 : Format[T6] ,
          bin7 : Format[T7] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in),
         read[T5](in),
         read[T6](in),
         read[T7](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
                  write(out, product._5);
                  write(out, product._6);
                  write(out, product._7);
        ;       
      }
    }  
  /**
   * Represents this type as 8 consecutive binary blocks of type T1..T8,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct8[S, T1,T2,T3,T4,T5,T6,T7,T8](apply : (T1,T2,T3,T4,T5,T6,T7,T8) => S)(unapply : S => Product8[T1,T2,T3,T4,T5,T6,T7,T8])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] ,
          bin5 : Format[T5] ,
          bin6 : Format[T6] ,
          bin7 : Format[T7] ,
          bin8 : Format[T8] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in),
         read[T5](in),
         read[T6](in),
         read[T7](in),
         read[T8](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
                  write(out, product._5);
                  write(out, product._6);
                  write(out, product._7);
                  write(out, product._8);
        ;       
      }
    }  
  /**
   * Represents this type as 9 consecutive binary blocks of type T1..T9,
   * relative to the specified way of decomposing and composing S as such.
   */
  def asProduct9[S, T1,T2,T3,T4,T5,T6,T7,T8,T9](apply : (T1,T2,T3,T4,T5,T6,T7,T8,T9) => S)(unapply : S => Product9[T1,T2,T3,T4,T5,T6,T7,T8,T9])(implicit
      bin1 : Format[T1] ,
          bin2 : Format[T2] ,
          bin3 : Format[T3] ,
          bin4 : Format[T4] ,
          bin5 : Format[T5] ,
          bin6 : Format[T6] ,
          bin7 : Format[T7] ,
          bin8 : Format[T8] ,
          bin9 : Format[T9] 
    ) = new Format[S]{
       def reads (in : Input) : S = apply(
         read[T1](in),
         read[T2](in),
         read[T3](in),
         read[T4](in),
         read[T5](in),
         read[T6](in),
         read[T7](in),
         read[T8](in),
         read[T9](in)
      )

      def writes(out : Output, s : S) = {
        val product = unapply(s);
          write(out, product._1);
                  write(out, product._2);
                  write(out, product._3);
                  write(out, product._4);
                  write(out, product._5);
                  write(out, product._6);
                  write(out, product._7);
                  write(out, product._8);
                  write(out, product._9);
        ;       
      }
    }  

  case class Summand[T](clazz : Class[_], format : Format[T]);
  implicit def classToSummand[T](clazz : Class[T])(implicit bin : Format[T]) : Summand[T] = Summand[T](clazz, bin);
  implicit def formatToSummand[T](format : Format[T])(implicit mf : scala.reflect.Manifest[T]) : Summand[T] = Summand[T](mf.erasure, format);
  // This is a bit gross. 
  implicit def anyToSummand[T](t : T) = Summand[T](t.asInstanceOf[AnyRef].getClass, asSingleton(t))

  /**
   * Uses a single tag byte to represent S as a union of subtypes. 
   */
  def asUnion[S](summands : Summand[_ <: S]*) : Format[S] = 
    if (summands.length >= 256) error("Sums of 256 or more elements currently not supported");
    else
    new Format[S]{
      val mappings = summands.toArray.zipWithIndex;

      def reads(in : Input) : S = read(in)(summands(read[Byte](in)).format)

      def writes(out : Output, s : S): Unit =
        mappings.find(_._1.clazz.isInstance(s)) match {
          case Some( (sum, i) ) => writeSum(out, s, sum, i)
          case None => error("No known sum type for object " + s);
        }
      private def writeSum[T](out : Output, s : S, sum : Summand[T], i : Int) {
        write(out, i.toByte);
        // 2.7/2.8 compatibility: cast added by MH
        write(out, sum.clazz.cast(s).asInstanceOf[T])(sum.format);
      }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy