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

scala.collection.compat.immutable.ArraySeq.scala Maven / Gradle / Ivy

The newest version!
/*
 * Scala (https://www.scala-lang.org)
 *
 * Copyright EPFL and Lightbend, Inc. dba Akka
 *
 * Licensed under Apache License 2.0
 * (http://www.apache.org/licenses/LICENSE-2.0).
 *
 * See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 */

package scala.collection.compat.immutable

import java.util.Arrays

import scala.annotation.unchecked.uncheckedVariance
import scala.collection.{AbstractSeq, IndexedSeqOptimized}
import scala.collection.generic._
import scala.collection.immutable.IndexedSeq
import scala.collection.mutable.{ArrayBuilder, Builder, WrappedArrayBuilder}
import scala.reflect.ClassTag
import scala.util.hashing.MurmurHash3

/**
 * An immutable array.
 *
 * Supports efficient indexed access and has a small memory footprint.
 *
 *  @define Coll `ArraySeq`
 *  @define coll wrapped array
 *  @define orderDependent
 *  @define orderDependentFold
 *  @define mayNotTerminateInf
 *  @define willNotTerminateInf
 */
abstract class ArraySeq[+T]
    extends AbstractSeq[T]
    with IndexedSeq[T]
    with IndexedSeqOptimized[T, ArraySeq[T]] {

  override protected[this] def thisCollection: ArraySeq[T] = this

  /** The tag of the element type */
  protected[this] def elemTag: ClassTag[T]

  /** The length of the array */
  def length: Int

  /** The element at given index */
  def apply(index: Int): T

  /** The underlying array */
  def unsafeArray: Array[T @uncheckedVariance]

  override def stringPrefix = "ArraySeq"

  /** Clones this object, including the underlying Array. */
  override def clone(): ArraySeq[T] = ArraySeq unsafeWrapArray unsafeArray.clone()

  /** Creates new builder for this collection ==> move to subclasses
   */
  override protected[this] def newBuilder: Builder[T, ArraySeq[T]] =
    ArraySeq.newBuilder[T](elemTag)

}

/** A companion object used to create instances of `ArraySeq`.
 */
object ArraySeq {
  // This is reused for all calls to empty.
  private val EmptyArraySeq = new ofRef[AnyRef](new Array[AnyRef](0))
  def empty[T <: AnyRef]: ArraySeq[T] = EmptyArraySeq.asInstanceOf[ArraySeq[T]]

  def newBuilder[T](implicit elemTag: ClassTag[T]): Builder[T, ArraySeq[T]] =
    new WrappedArrayBuilder[T](elemTag).mapResult(w => unsafeWrapArray(w.array))

  def apply[T](elems: T*)(implicit elemTag: ClassTag[T]): ArraySeq[T] = {
    val b = newBuilder[T]
    b ++= elems
    b.result()
  }

  def unapplySeq[T](seq: ArraySeq[T]): Some[ArraySeq[T]] = Some(seq)

  /**
   * Wrap an existing `Array` into an `ArraySeq` of the proper primitive specialization type
   * without copying.
   *
   * Note that an array containing boxed primitives can be wrapped in an `ArraySeq` without
   * copying. For example, `val a: Array[Any] = Array(1)` is an array of `Object` at runtime,
   * containing `Integer`s. An `ArraySeq[Int]` can be obtained with a cast:
   * `ArraySeq.unsafeWrapArray(a).asInstanceOf[ArraySeq[Int]]`. The values are still
   * boxed, the resulting instance is an [[ArraySeq.ofRef]]. Writing
   * `ArraySeq.unsafeWrapArray(a.asInstanceOf[Array[Int]])` does not work, it throws a
   * `ClassCastException` at runtime.
   */
  def unsafeWrapArray[T](x: Array[T]): ArraySeq[T] =
    (x.asInstanceOf[Array[_]] match {
      case null => null
      case x: Array[AnyRef] => new ofRef[AnyRef](x)
      case x: Array[Int] => new ofInt(x)
      case x: Array[Double] => new ofDouble(x)
      case x: Array[Long] => new ofLong(x)
      case x: Array[Float] => new ofFloat(x)
      case x: Array[Char] => new ofChar(x)
      case x: Array[Byte] => new ofByte(x)
      case x: Array[Short] => new ofShort(x)
      case x: Array[Boolean] => new ofBoolean(x)
      case x: Array[Unit] => new ofUnit(x)
    }).asInstanceOf[ArraySeq[T]]

  implicit def canBuildFrom[T](implicit m: ClassTag[T]): CanBuildFrom[ArraySeq[_], T, ArraySeq[T]] =
    new CanBuildFrom[ArraySeq[_], T, ArraySeq[T]] {
      def apply(from: ArraySeq[_]): Builder[T, ArraySeq[T]] =
        ArrayBuilder.make[T]()(m) mapResult ArraySeq.unsafeWrapArray[T]
      def apply: Builder[T, ArraySeq[T]] =
        ArrayBuilder.make[T]()(m) mapResult ArraySeq.unsafeWrapArray[T]
    }

  private def unsupportedUpdate: Nothing =
    throw new UnsupportedOperationException("immutable ArraySeq does not support mutation")

  private final val updateDeprecationMsg =
    "Mutation is not supported for immutable ArraySeq, and should not have ever been " +
      "part of the API"

  @SerialVersionUID(3L)
  final class ofRef[T <: AnyRef](val unsafeArray: Array[T]) extends ArraySeq[T] with Serializable {
    lazy val elemTag = ClassTag[T](unsafeArray.getClass.getComponentType)
    def length: Int = unsafeArray.length
    def apply(index: Int): T = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: T): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofRef[_] =>
        arrayEquals(
          unsafeArray.asInstanceOf[Array[AnyRef]],
          that.unsafeArray.asInstanceOf[Array[AnyRef]])
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofByte(val unsafeArray: Array[Byte]) extends ArraySeq[Byte] with Serializable {
    def elemTag = ClassTag.Byte
    def length: Int = unsafeArray.length
    def apply(index: Int): Byte = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Byte): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofByte => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofShort(val unsafeArray: Array[Short]) extends ArraySeq[Short] with Serializable {
    def elemTag = ClassTag.Short
    def length: Int = unsafeArray.length
    def apply(index: Int): Short = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Short): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofShort => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofChar(val unsafeArray: Array[Char]) extends ArraySeq[Char] with Serializable {
    def elemTag = ClassTag.Char
    def length: Int = unsafeArray.length
    def apply(index: Int): Char = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Char): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofChar => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofInt(val unsafeArray: Array[Int]) extends ArraySeq[Int] with Serializable {
    def elemTag = ClassTag.Int
    def length: Int = unsafeArray.length
    def apply(index: Int): Int = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Int): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofInt => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofLong(val unsafeArray: Array[Long]) extends ArraySeq[Long] with Serializable {
    def elemTag = ClassTag.Long
    def length: Int = unsafeArray.length
    def apply(index: Int): Long = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Long): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofLong => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofFloat(val unsafeArray: Array[Float]) extends ArraySeq[Float] with Serializable {
    def elemTag = ClassTag.Float
    def length: Int = unsafeArray.length
    def apply(index: Int): Float = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Float): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofFloat => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofDouble(val unsafeArray: Array[Double]) extends ArraySeq[Double] with Serializable {
    def elemTag = ClassTag.Double
    def length: Int = unsafeArray.length
    def apply(index: Int): Double = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Double): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofDouble => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofBoolean(val unsafeArray: Array[Boolean])
      extends ArraySeq[Boolean]
      with Serializable {
    def elemTag = ClassTag.Boolean
    def length: Int = unsafeArray.length
    def apply(index: Int): Boolean = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Boolean): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofBoolean => Arrays.equals(unsafeArray, that.unsafeArray)
      case _ => super.equals(that)
    }
  }

  @SerialVersionUID(3L)
  final class ofUnit(val unsafeArray: Array[Unit]) extends ArraySeq[Unit] with Serializable {
    def elemTag = ClassTag.Unit
    def length: Int = unsafeArray.length
    def apply(index: Int): Unit = unsafeArray(index)
    @deprecated(updateDeprecationMsg, since = "2.4.2")
    def update(index: Int, elem: Unit): Unit = unsupportedUpdate
    override def hashCode = MurmurHash3.arrayHash(unsafeArray, MurmurHash3.seqSeed)
    override def equals(that: Any) = that match {
      case that: ofUnit => unsafeArray.length == that.unsafeArray.length
      case _ => super.equals(that)
    }
  }

  private[this] def arrayEquals(xs: Array[AnyRef], ys: Array[AnyRef]): Boolean = {
    if (xs eq ys)
      return true
    if (xs.length != ys.length)
      return false

    val len = xs.length
    var i = 0
    while (i < len) {
      if (xs(i) != ys(i))
        return false
      i += 1
    }
    true
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy