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

izumi.thirdparty.internal.boopickle.IdentList.scala Maven / Gradle / Ivy

package izumi.thirdparty.internal.boopickle

import scala.collection.mutable

/**
  * Specialized fast and cheap to initialize identity list for unpickle state identifier refs
  */
private[izumi] abstract class IdentList {
  @noinline def apply(idx: Int): AnyRef

  @noinline def updated(obj: AnyRef): IdentList
}

private[izumi] object IdentList {

  private[boopickle] final class Entry(val obj: AnyRef, var next: Entry)
  private[boopickle] val maxSize = 32
}

private[izumi] object EmptyIdentList extends IdentList {
  override def apply(idx: Int): AnyRef = throw new IndexOutOfBoundsException

  override def updated(obj: AnyRef): IdentList = new IdentList1Plus(obj)
}

/**
  * A fast and simple linked list implementation for identifier list
  *
  * @param o1 First object
  */
private[boopickle] final class IdentList1Plus(o1: AnyRef) extends IdentList {
  import IdentList.Entry
  var last: Entry = new Entry(o1, null)
  var head: Entry = last
  var switchOver  = false
  var size        = 0

  override def apply(idx: Int): AnyRef = {
    // first time something is looked up, we switch to the more efficient implementation
    switchOver = true
    var i = 0
    var e = head
    while (i < idx && e != null) {
      i += 1
      e = e.next
    }
    if (e == null)
      throw new IndexOutOfBoundsException
    e.obj
  }

  override def updated(obj: AnyRef): IdentList = {
    val e = new Entry(obj, null)
    last.next = e
    last = e
    size += 1
    if (switchOver || size > IdentList.maxSize)
      new IdentListBig(head, size)
    else
      this
  }
}

/**
  * A more scalable implementation for an identifier list
  *
  * @param first First entry in a list of entries
  */
private[boopickle] final class IdentListBig(first: IdentList.Entry, size: Int) extends IdentList {
  // transform the linked list into an array buffer
  val b = mutable.ArrayBuffer.newBuilder[AnyRef]
  b.sizeHint(size)
  var e = first
  while (e != null) {
    b += e.obj
    e = e.next
  }
  val entries = b.result()

  override def apply(idx: Int): AnyRef = {
    entries(idx)
  }

  override def updated(obj: AnyRef): IdentList = {
    entries += obj
    this
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy