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

zio.internal.PinchableArray.scala Maven / Gradle / Ivy

There is a newer version: 2.1.11
Show newest version
/*
 * Copyright 2022-2024 John A. De Goes and the ZIO Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package zio.internal

import scala.reflect.ClassTag

import zio.Chunk

private[zio] final class PinchableArray[A: ClassTag](hint: Int) extends Iterable[A] { self =>
  import java.lang.System

  private var array  = if (hint < 0) null else new Array[A](hint)
  private var _pinch = null.asInstanceOf[Array[A]]
  private var _size  = 0

  def +=(a: A): Unit = {
    ensureCapacity(1)

    array(_size) = a
    _size += 1
  }

  def ++=(as: Chunk[A]): Unit = {
    ensureCapacity(as.length)

    as.copyToArray(array, _size)

    _size = _size + as.length
  }

  def apply(index: Int): A = array(index) // No error checking for performance

  def ensureCapacity(elements: Int): Unit = {
    val newSize = _size + elements

    if (array eq null) {
      array = new Array[A](newSize)
    } else if (newSize > array.length) {
      val newStack = new Array[A](newSize + _size / 2)
      System.arraycopy(array, 0, newStack, 0, _size)
      array = newStack
    }
  }

  def iterator: Iterator[A] =
    new Iterator[A] {
      var index = 0

      def hasNext: Boolean = index < self._size

      def next(): A = {
        if (!hasNext) throw new NoSuchElementException("There are no elements to iterate")

        val value = self.array(index)

        index = index + 1

        value
      }
    }

  def length: Int = _size

  def pinch(): Chunk[A] = {
    val size = self._size

    if (size == 0) Chunk.empty
    else {
      ensurePinchCapacity(size)

      System.arraycopy(array, 0, _pinch, 0, size)

      _size = 0

      Chunk.fromArray(_pinch).take(size)
    }
  }

  private[zio] def asChunk(): Chunk[A] =
    if (array eq null) Chunk.empty
    else Chunk.fromArray(array).take(_size)

  private def ensurePinchCapacity(newSize: Int): Unit =
    if (_pinch eq null) {
      _pinch = new Array[A](newSize)
    } else if (newSize > _pinch.length) {
      _pinch = new Array[A](newSize)
    }

  override def toString(): String = self.mkString("PinchableArray(", ",", ")")
}
private[zio] object PinchableArray {
  def make[A: ClassTag](hint: Int): PinchableArray[A] = new PinchableArray[A](hint)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy