Skip to content

Instantly share code, notes, and snippets.

@PhBastiani
Last active June 13, 2020 15:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PhBastiani/9e494f7fd971848296914c775f052cbe to your computer and use it in GitHub Desktop.
Save PhBastiani/9e494f7fd971848296914c775f052cbe to your computer and use it in GitHub Desktop.
WIP : use of the new Arrow Fx DSL - java.io integration
import arrow.core.Either
import arrow.fx.coroutines.Resource
import arrow.fx.coroutines.unit
import java.io.*
interface InputStream {
val s: FileInputStream
suspend fun read(buf: ByteArray, off: Int, len: Int): Int =
s.read(buf, off, len)
suspend fun close() = s.close()
companion object {
fun stream(f: File) = object : InputStream {
override val s = FileInputStream(f)
}
}
}
interface OutputStream {
val s: FileOutputStream
suspend fun write(buf: ByteArray, off: Int, len: Int) =
s.write(buf, off, len)
suspend fun close() = s.close()
companion object {
fun stream(f: File) = object : OutputStream {
override val s = FileOutputStream(f)
}
}
}
data class CopyService(private val consumer: InputStream, private val supplier: OutputStream) {
private tailrec suspend fun copy(origin: InputStream, destination: OutputStream, buffer: ByteArray, acc: Long): Long {
val amount = origin.read(buffer, 0, buffer.size)
return if (amount >= 0) {
destination.write(buffer, 0, amount)
copy(origin, destination, buffer, acc + amount)
} else acc
}
suspend fun process() = copy(consumer, supplier, ByteArray(4096), 0)
}
val resourceCopy = { src: File, dest: File ->
Resource({ InputStream.stream(src) }, InputStream::close)
.zip(Resource({ OutputStream.stream(dest) }, OutputStream::close))
.flatMap { (consumer, supplier) ->
Resource({ CopyService(consumer, supplier) }, { _ -> unit() })
}
}
suspend fun main(args: Array<String>) {
if (args.size == 2) {
Either.catch {
val source = File(args[0])
val target = File(args[1])
resourceCopy(source, target).use {
val copied = it.process()
println("$copied bytes copied from ${source.path} to ${target.path}")
Unit
}
}.fold(
{ println("Failure: ${it.message}") },
{ println("Success.") }
)
} else {
println("Failure: 2 arguments are required...")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment