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

eu.joaocosta.minart.internal.ByteWriter.scala Maven / Gradle / Ivy

package eu.joaocosta.minart.internal

import java.io.OutputStream

/** Helper methods to write binary data to an output stream.
  */
private[minart] trait ByteWriter[ByteStream] {
  type ByteStreamState[E] = State[ByteStream, E, Unit]

  /** Writes a ByteStream to a output stream */
  def toOutputStream[E](data: ByteStreamState[E], os: OutputStream): Either[E, Unit]

  /** Empty state */
  def emptyStream: ByteStreamState[Nothing] = State.pure(())

  /** Appends this byte stream to the current accumulator */
  def append(stream: ByteStream): ByteStreamState[Nothing]

  /** Adds a sequence of bytes to the tail of the byte stream */
  def writeBytes(bytes: Seq[Int]): ByteStreamState[String]

  /** Write 1 Byte */
  def writeByte(byte: Int): ByteStreamState[String] = writeBytes(Seq(byte))

  /** Writes a String */
  def writeString(string: String): ByteStreamState[String] =
    writeBytes(string.map(_.toInt))

  /** Writes a String Line */
  def writeStringLn(string: String, delimiter: String = "\n"): ByteStreamState[String] =
    writeString(string + delimiter)

  /** Writes a Integer in N Bytes (Little Endian) */
  def writeLENumber(value: Int, bytes: Int): ByteStreamState[String] =
    writeBytes((0 until bytes).map { idx => (value >> (idx * 8)) & 0x000000ff })

  /** Writes a Integer in N Bytes (Big Endian) */
  def writeBENumber(value: Int, bytes: Int): ByteStreamState[String] =
    writeBytes((0 until bytes).reverse.map { idx => (value >> (idx * 8)) & 0x000000ff })
}

private[minart] object ByteWriter {
  object IteratorByteWriter extends ByteWriter[Iterator[Array[Byte]]] {
    def toOutputStream[E](data: ByteStreamState[E], os: OutputStream): Either[E, Unit] =
      data.run(Iterator.empty).map { case (s, _) =>
        s.foreach(bytes => os.write(bytes))
      }

    def append(stream: Iterator[Array[Byte]]): ByteStreamState[Nothing] =
      State.modify[Iterator[Array[Byte]]](s => s ++ stream)

    def writeBytes(bytes: Seq[Int]): ByteStreamState[String] =
      if (bytes.forall(b => b >= 0 && b <= 255)) append(Iterator(bytes.map(_.toByte).toArray))
      else State.error(s"Sequence $bytes contains invalid bytes")
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy