2009-03-22 17:26:42 +01:00
|
|
|
/**
|
2011-07-14 16:03:08 +02:00
|
|
|
* Copyright (C) 2009-2011 Typesafe Inc. <http://www.typesafe.com>
|
2009-03-22 17:26:42 +01:00
|
|
|
*/
|
2010-10-26 12:49:25 +02:00
|
|
|
package akka.util
|
2009-03-22 17:26:42 +01:00
|
|
|
|
2011-09-08 11:02:17 +02:00
|
|
|
import java.io.{ PrintWriter, StringWriter }
|
2011-11-11 17:44:57 +01:00
|
|
|
import java.util.Comparator
|
2011-04-28 20:12:37 +02:00
|
|
|
|
2009-03-22 17:26:42 +01:00
|
|
|
/**
|
|
|
|
|
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
|
|
|
|
*/
|
2011-02-28 22:54:32 +01:00
|
|
|
object Helpers {
|
2009-03-22 17:26:42 +01:00
|
|
|
|
2010-09-28 11:21:05 +02:00
|
|
|
implicit def null2Option[T](t: T): Option[T] = Option(t)
|
2009-08-11 13:13:16 +02:00
|
|
|
|
2011-11-11 17:44:57 +01:00
|
|
|
def compareIdentityHash(a: AnyRef, b: AnyRef): Int = {
|
|
|
|
|
/*
|
|
|
|
|
* make sure that there is no overflow or underflow in comparisons, so
|
|
|
|
|
* that the ordering is actually consistent and you cannot have a
|
|
|
|
|
* sequence which cyclically is monotone without end.
|
|
|
|
|
*/
|
|
|
|
|
val diff = ((System.identityHashCode(a) & 0xffffffffL) - (System.identityHashCode(b) & 0xffffffffL))
|
|
|
|
|
if (diff > 0) 1 else if (diff < 0) -1 else 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val IdentityHashComparator = new Comparator[AnyRef] {
|
|
|
|
|
def compare(a: AnyRef, b: AnyRef): Int = compareIdentityHash(a, b)
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-11 13:13:16 +02:00
|
|
|
def intToBytes(value: Int): Array[Byte] = {
|
|
|
|
|
val bytes = new Array[Byte](4)
|
|
|
|
|
bytes(0) = (value >>> 24).asInstanceOf[Byte]
|
|
|
|
|
bytes(1) = (value >>> 16).asInstanceOf[Byte]
|
|
|
|
|
bytes(2) = (value >>> 8).asInstanceOf[Byte]
|
|
|
|
|
bytes(3) = value.asInstanceOf[Byte]
|
|
|
|
|
bytes
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-26 12:04:32 +02:00
|
|
|
def bytesToInt(bytes: Array[Byte], offset: Int): Int = {
|
2011-05-18 17:25:30 +02:00
|
|
|
(0 until 4).foldLeft(0)((value, index) ⇒ value + ((bytes(index + offset) & 0x000000FF) << ((4 - 1 - index) * 8)))
|
2009-07-23 20:01:37 +02:00
|
|
|
}
|
2009-03-22 17:26:42 +01:00
|
|
|
|
2011-05-18 17:25:30 +02:00
|
|
|
def ignore[E: Manifest](body: ⇒ Unit) {
|
2011-04-28 20:12:37 +02:00
|
|
|
try {
|
|
|
|
|
body
|
2011-05-18 17:25:30 +02:00
|
|
|
} catch {
|
|
|
|
|
case e if manifest[E].erasure.isAssignableFrom(e.getClass) ⇒ ()
|
2011-04-28 20:12:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-18 17:25:30 +02:00
|
|
|
def withPrintStackTraceOnError(body: ⇒ Unit) {
|
2011-04-28 20:12:37 +02:00
|
|
|
try {
|
|
|
|
|
body
|
|
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: Throwable ⇒
|
2011-09-08 11:02:17 +02:00
|
|
|
val sw = new java.io.StringWriter()
|
|
|
|
|
var root = e
|
|
|
|
|
while (root.getCause ne null) root = e.getCause
|
|
|
|
|
root.printStackTrace(new java.io.PrintWriter(sw))
|
|
|
|
|
System.err.println(sw.toString)
|
2011-04-28 20:12:37 +02:00
|
|
|
throw e
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-18 16:31:25 +02:00
|
|
|
/**
|
|
|
|
|
* Convenience helper to cast the given Option of Any to an Option of the given type. Will throw a ClassCastException
|
|
|
|
|
* if the actual type is not assignable from the given one.
|
|
|
|
|
*/
|
|
|
|
|
def narrow[T](o: Option[Any]): Option[T] = {
|
2010-09-28 11:21:05 +02:00
|
|
|
require((o ne null), "Option to be narrowed must not be null!")
|
2010-06-18 16:31:25 +02:00
|
|
|
o.asInstanceOf[Option[T]]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible
|
|
|
|
|
* ClassCastException and return None in that case.
|
|
|
|
|
*/
|
|
|
|
|
def narrowSilently[T: Manifest](o: Option[Any]): Option[T] =
|
|
|
|
|
try {
|
|
|
|
|
narrow(o)
|
|
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: ClassCastException ⇒
|
2010-06-18 16:31:25 +02:00
|
|
|
None
|
|
|
|
|
}
|
2010-10-29 16:33:31 +02:00
|
|
|
|
2010-10-26 12:04:32 +02:00
|
|
|
/**
|
|
|
|
|
* Reference that can hold either a typed value or an exception.
|
|
|
|
|
*
|
|
|
|
|
* Usage:
|
|
|
|
|
* <pre>
|
|
|
|
|
* scala> ResultOrError(1)
|
|
|
|
|
* res0: ResultOrError[Int] = ResultOrError@a96606
|
|
|
|
|
*
|
|
|
|
|
* scala> res0()
|
2011-05-18 17:25:30 +02:00
|
|
|
* res1: Int = 1
|
2010-10-26 12:04:32 +02:00
|
|
|
*
|
|
|
|
|
* scala> res0() = 3
|
|
|
|
|
*
|
|
|
|
|
* scala> res0()
|
|
|
|
|
* res3: Int = 3
|
2010-10-29 16:33:31 +02:00
|
|
|
*
|
2010-10-26 12:04:32 +02:00
|
|
|
* scala> res0() = { println("Hello world"); 3}
|
|
|
|
|
* Hello world
|
|
|
|
|
*
|
|
|
|
|
* scala> res0()
|
|
|
|
|
* res5: Int = 3
|
2010-10-29 16:33:31 +02:00
|
|
|
*
|
2010-10-26 12:04:32 +02:00
|
|
|
* scala> res0() = error("Lets see what happens here...")
|
|
|
|
|
*
|
|
|
|
|
* scala> res0()
|
|
|
|
|
* java.lang.RuntimeException: Lets see what happens here...
|
2010-10-26 23:44:13 +02:00
|
|
|
* at ResultOrError.apply(Helper.scala:11)
|
|
|
|
|
* at .<init>(<console>:6)
|
|
|
|
|
* at .<clinit>(<console>)
|
|
|
|
|
* at Re...
|
2010-10-26 12:04:32 +02:00
|
|
|
* </pre>
|
|
|
|
|
*/
|
2011-05-18 17:25:30 +02:00
|
|
|
class ResultOrError[R](result: R) {
|
2010-10-26 12:04:32 +02:00
|
|
|
private[this] var contents: Either[R, Throwable] = Left(result)
|
2010-10-29 16:33:31 +02:00
|
|
|
|
2011-05-18 17:25:30 +02:00
|
|
|
def update(value: ⇒ R) {
|
2010-10-29 16:33:31 +02:00
|
|
|
contents = try {
|
|
|
|
|
Left(value)
|
|
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case (error: Throwable) ⇒ Right(error)
|
2010-10-29 16:33:31 +02:00
|
|
|
}
|
2010-10-26 12:04:32 +02:00
|
|
|
}
|
2010-10-29 16:33:31 +02:00
|
|
|
|
2010-10-26 12:04:32 +02:00
|
|
|
def apply() = contents match {
|
2011-05-18 17:25:30 +02:00
|
|
|
case Left(result) ⇒ result
|
|
|
|
|
case Right(error) ⇒ throw error.fillInStackTrace
|
2010-10-26 12:04:32 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
object ResultOrError {
|
|
|
|
|
def apply[R](result: R) = new ResultOrError(result)
|
|
|
|
|
}
|
2010-06-18 16:31:25 +02:00
|
|
|
}
|