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

pickling.fastbinary.Output.scala Maven / Gradle / Ivy

The newest version!
package scala.pickling.fastbinary

import java.io.OutputStream
import scala.pickling.ArrayOutput


object FastArrayOutput {

  private[pickling] val arrayBuilder = new ThreadLocal[ByteArrayBuilder] {
    // initially a builder with pre-allocated array
    override def initialValue(): ByteArrayBuilder = new ByteArray(64 * 1024 * 1024) // 64 MB
  }

}

class FastArrayOutput extends ArrayOutput[Byte] {

  private var builder: ByteArrayBuilder = {
    val b = FastArrayOutput.arrayBuilder.get()
    val reuse = b.checkpoint()
    if (!reuse) {
      // allocate new array builder
      val newb = new ByteArray(64 * 1024 * 1024) // 64 MB
      // put into thread-local storage
      FastArrayOutput.arrayBuilder.set(newb)
      newb.checkpoint() // guaranteed to return `true`
      newb
    } else b
  }

  // replace `builder` with a growable one
  private def replaceBuilder(): Unit = {
    builder = new ByteArrayBuffer(builder.toArray)
    FastArrayOutput.arrayBuilder.set(builder)
  }

  def result(): Array[Byte] = builder.toArray

  def +=(obj: Byte) = {
    // if builder is full replace `builder` with a growable one
    if (builder.isFull) replaceBuilder()
    builder += obj
  }

  def put(obj: Array[Byte]): this.type = {
    // should use `target`
    throw new java.lang.IllegalStateException
  }

  override def target(l: Int) = try {
    builder.target(l)
  } catch {
    case e: IllegalArgumentException =>
      // `builder` does not have enough space
      replaceBuilder()
      builder.target(l) // guaranteed to succeed
  }

  override def flush(a: Array[Byte]) =
    builder.flush(a)
}


final class FastOutputStreamOutput(out: OutputStream) extends FastArrayOutput {
  override def result(): Array[Byte] =
    null

  override def +=(obj: Byte) =
    out.write(obj.asInstanceOf[Int])

  override def put(obj: Array[Byte]): this.type = {
    out.write(obj)
    this
  }

  override def target(len: Int): (Array[Byte], Int) =
    (Array.ofDim[Byte](len), 0)

  override def flush(arr: Array[Byte]): Unit =
    this.put(arr)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy