sbt.incremental-compiler.0.13.1.source-code.generic.scala Maven / Gradle / Ivy
/**
* 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