Cute piece of code for statically checking array index accesses.
package ranges;
class Range(val start : Int, val end : Int){
if (start >= end) throw new IndexOutOfBoundsException();
def checkRange(min : Int, max : Int){
if (min < start || max > end) throw new IndexOutOfBoundsException();
}
def inBounds(x : Int) : Index = unsafeFromInt(Math.min(end - 1, Math.max(x, start)));
def checkBounds (x : Int) : Index = if (x < start || x >= end) throw new IndexOutOfBoundsException() else unsafeFromInt(x);
private[Range] def unsafeFromInt (i : Int) = Index(i); // Separated into a method for refactoring and unsafe declaration.
val range = start until end;
val length = end - start;
val maxIndex = unsafeFromInt(end - 1);
val minIndex = unsafeFromInt(start);
val indices = range.map(unsafeFromInt(_));
trait Slice[T] extends Iterable[T] {
def apply(i : Index) : T = unsafeApply(i);
def update(i : Index, t : T) = unsafeUpdate(i, t);
private[Range] def unsafeApply(i : Int) : T;
private[Range] def unsafeUpdate(i : Int, t : T) : Unit;
def elements = range.elements.map(unsafeApply(_));
}
class ArraySlice[T](array : Array[T]) extends Slice[T]{
if (length < end) throw new IndexOutOfBoundsException();
private[Range] def unsafeApply(i : Int) = array(i);
private[Range] def unsafeUpdate(i : Int, t : T) : Unit = array(i) = t;
override def foreach(f : T => Unit) = for (val i <- range) array(i);
}
class CheckedArray[T] extends Slice[T]{
private val array = new Array[T](length);
private[Range] def unsafeApply(i : Int) = array(i - start);
private[Range] def unsafeUpdate(i : Int, t : T) : Unit = array(i - start) = t;
override def foreach(f : T => Unit) = array.foreach(f);
}
implicit def toInteger(i : Index) = i.toInt;
case class Index private[Range] (val toInt : Int){
def max(y : Index) = unsafeFromInt(Math.max(this, y));
def min(y : Index) = unsafeFromInt(Math.min(this, y));
def mid(y : Index) = unsafeFromInt((this + y) >>> 1);
def opposite = unsafeFromInt(end + start - 1 - this);
};
}