package scala.reflect
import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
import java.lang.{ Class => JClass }
trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
def erasure: JClass[_]
private def subtype(sub: JClass[_], sup: JClass[_]): Boolean = {
def loop(left: Set[JClass[_]], seen: Set[JClass[_]]): Boolean = {
left.nonEmpty && {
val next = left.head
val supers = next.getInterfaces.toSet ++ Option(next.getSuperclass)
supers(sup) || {
val xs = left ++ supers filterNot seen
loop(xs - next, seen + next)
}
}
}
loop(Set(sub), Set())
}
private def subargs(args1: List[OptManifest[_]], args2: List[OptManifest[_]]) = (args1 corresponds args2) {
case (x: ClassManifest[_], y: ClassManifest[_]) => x <:< y
case (x, y) => (x eq NoManifest) && (y eq NoManifest)
}
def <:<(that: ClassManifest[_]): Boolean = {
def cannotMatch = {
import Manifest._
that.isInstanceOf[AnyValManifest[_]] || (that eq AnyVal) || (that eq Nothing) || (that eq Null)
}
!cannotMatch && {
if (this.erasure == that.erasure)
subargs(this.typeArguments, that.typeArguments)
else
that.typeArguments.isEmpty && subtype(this.erasure, that.erasure)
}
}
def >:>(that: ClassManifest[_]): Boolean =
that <:< this
def canEqual(other: Any) = other match {
case _: ClassManifest[_] => true
case _ => false
}
override def equals(that: Any): Boolean = that match {
case m: ClassManifest[_] => (m canEqual this) && (this.erasure == m.erasure)
case _ => false
}
override def hashCode = this.erasure.##
protected def arrayClass[T](tp: JClass[_]): JClass[Array[T]] =
java.lang.reflect.Array.newInstance(tp, 0).getClass.asInstanceOf[JClass[Array[T]]]
def arrayManifest: ClassManifest[Array[T]] =
ClassManifest.classType[Array[T]](arrayClass[T](erasure))
def newArray(len: Int): Array[T] =
java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
def newArray2(len: Int): Array[Array[T]] =
java.lang.reflect.Array.newInstance(arrayClass[T](erasure), len)
.asInstanceOf[Array[Array[T]]]
def newArray3(len: Int): Array[Array[Array[T]]] =
java.lang.reflect.Array.newInstance(arrayClass[Array[T]](arrayClass[T](erasure)), len)
.asInstanceOf[Array[Array[Array[T]]]]
def newArray4(len: Int): Array[Array[Array[Array[T]]]] =
java.lang.reflect.Array.newInstance(arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure))), len)
.asInstanceOf[Array[Array[Array[Array[T]]]]]
def newArray5(len: Int): Array[Array[Array[Array[Array[T]]]]] =
java.lang.reflect.Array.newInstance(arrayClass[Array[Array[Array[T]]]](arrayClass[Array[Array[T]]](arrayClass[Array[T]](arrayClass[T](erasure)))), len)
.asInstanceOf[Array[Array[Array[Array[Array[T]]]]]]
def newWrappedArray(len: Int): WrappedArray[T] =
new WrappedArray.ofRef[T with AnyRef](newArray(len).asInstanceOf[Array[T with AnyRef]]).asInstanceOf[WrappedArray[T]]
def newArrayBuilder(): ArrayBuilder[T] =
new ArrayBuilder.ofRef[T with AnyRef]()(this.asInstanceOf[ClassManifest[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
def typeArguments: List[OptManifest[_]] = List()
protected def argString =
if (typeArguments.nonEmpty) typeArguments.mkString("[", ", ", "]")
else if (erasure.isArray) "["+ClassManifest.fromClass(erasure.getComponentType)+"]"
else ""
}
object ClassManifest {
val Byte = Manifest.Byte
val Short = Manifest.Short
val Char = Manifest.Char
val Int = Manifest.Int
val Long = Manifest.Long
val Float = Manifest.Float
val Double = Manifest.Double
val Boolean = Manifest.Boolean
val Unit = Manifest.Unit
val Any = Manifest.Any
val Object = Manifest.Object
val AnyVal = Manifest.AnyVal
val Nothing = Manifest.Nothing
val Null = Manifest.Null
def fromClass[T](clazz: JClass[T]): ClassManifest[T] = clazz match {
case java.lang.Byte.TYPE => Byte.asInstanceOf[ClassManifest[T]]
case java.lang.Short.TYPE => Short.asInstanceOf[ClassManifest[T]]
case java.lang.Character.TYPE => Char.asInstanceOf[ClassManifest[T]]
case java.lang.Integer.TYPE => Int.asInstanceOf[ClassManifest[T]]
case java.lang.Long.TYPE => Long.asInstanceOf[ClassManifest[T]]
case java.lang.Float.TYPE => Float.asInstanceOf[ClassManifest[T]]
case java.lang.Double.TYPE => Double.asInstanceOf[ClassManifest[T]]
case java.lang.Boolean.TYPE => Boolean.asInstanceOf[ClassManifest[T]]
case java.lang.Void.TYPE => Unit.asInstanceOf[ClassManifest[T]]
case _ => classType[T with AnyRef](clazz).asInstanceOf[ClassManifest[T]]
}
def singleType[T <: AnyRef](value: AnyRef): Manifest[T] = Manifest.singleType(value)
def classType[T <: AnyRef](clazz: JClass[_]): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, Nil)
def classType[T <: AnyRef](clazz: JClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
def classType[T <: AnyRef](prefix: OptManifest[_], clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
case NoManifest => Object.asInstanceOf[ClassManifest[Array[T]]]
case m: ClassManifest[_] => m.asInstanceOf[ClassManifest[T]].arrayManifest
}
def abstractType[T](prefix: OptManifest[_], name: String, clazz: JClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassManifest[T] {
def erasure = clazz
override val typeArguments = args.toList
override def toString = prefix.toString+"#"+name+argString
}
def abstractType[T](prefix: OptManifest[_], name: String, upperbound: ClassManifest[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassManifest[T] {
def erasure = upperbound.erasure
override val typeArguments = args.toList
override def toString = prefix.toString+"#"+name+argString
}
}
private class ClassTypeManifest[T <: AnyRef](
prefix: Option[OptManifest[_]],
val erasure: JClass[_],
override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
{
override def toString =
(if (prefix.isEmpty) "" else prefix.get.toString+"#") +
(if (erasure.isArray) "Array" else erasure.getName) +
argString
}