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

replpp.shaded.os.Source.scala Maven / Gradle / Ivy

The newest version!
package replpp.shaded
package os

import java.io.{
  ByteArrayInputStream,
  InputStream,
  OutputStream,
  SequenceInputStream,
  BufferedOutputStream
}
import java.nio.channels.{
  Channels,
  FileChannel,
  ReadableByteChannel,
  SeekableByteChannel,
  WritableByteChannel
}

import scala.language.implicitConversions

/**
 * A source of bytes; must provide either an [[InputStream]] or a
 * [[SeekableByteChannel]] to read from. Can be constructed implicitly from
 * strings, byte arrays, inputstreams, channels or file paths
 */
trait Source extends geny.Writable {
  override def httpContentType = Some("application/octet-stream")
  def getHandle(): Either[geny.Writable, SeekableByteChannel]
  def writeBytesTo(out: java.io.OutputStream) = getHandle() match {
    case Left(bs) => bs.writeBytesTo(out)

    case Right(channel: FileChannel) =>
      val outChannel = Channels.newChannel(out)
      channel.transferTo(0, Long.MaxValue, outChannel)

    case Right(channel) =>
      val inChannel = Channels.newInputStream(channel)
      Internals.transfer(inChannel, out)
  }
  def writeBytesTo(out: WritableByteChannel) = getHandle() match {
    case Left(bs) =>
      val os = new BufferedOutputStream(Channels.newOutputStream(out))
      bs.writeBytesTo(os)
      os.flush()
    case Right(channel) =>
      (channel, out) match {
        case (src: FileChannel, dest) =>
          val size = src.size()
          var pos = 0L
          while (pos < size) {
            pos += src.transferTo(pos, size - pos, dest)
          }
        case (src, dest: FileChannel) => dest.transferFrom(src, 0, Long.MaxValue)
        case (src, dest) =>
          val os = new BufferedOutputStream(Channels.newOutputStream(dest))
          Internals.transfer(Channels.newInputStream(src), os)
          os.flush()
      }

  }
}

object Source extends WritableLowPri {
  implicit class ChannelSource(cn: SeekableByteChannel) extends Source {
    def getHandle() = Right(cn)
  }

  implicit class WritableSource[T](s: T)(implicit f: T => geny.Writable) extends Source {
    val writable = f(s)
    def getHandle() = Left(writable)
  }
}

trait WritableLowPri {
  implicit def WritableGenerator[T](a: geny.Generator[T])(implicit
      f: T => geny.Writable
  ): Source = {
    val f0 = f
    new Source {
      def getHandle() = Left(
        new geny.Writable {
          def writeBytesTo(out: java.io.OutputStream) = {
            for (x <- a) f0(x).writeBytesTo(out)
          }
        }
      )
    }
  }
  implicit def WritableTraversable[M[_], T](a: M[T])(implicit
      f: T => geny.Writable,
      g: M[T] => TraversableOnce[T]
  ): Source = {
    val traversable = g(a)
    val f0 = f
    new Source {
      def getHandle() = Left(
        new geny.Writable {
          def writeBytesTo(out: java.io.OutputStream) = {
            for (x <- traversable) f0(x).writeBytesTo(out)
          }
        }
      )
    }
  }
}

/**
 * A source which is guaranteeds to provide a [[SeekableByteChannel]]
 */
trait SeekableSource extends Source {
  def getHandle(): Right[geny.Writable, SeekableByteChannel]
  def getChannel() = getHandle().right.get
}

object SeekableSource {
  implicit class ChannelSource(cn: SeekableByteChannel) extends SeekableSource {
    def getHandle() = Right(cn)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy