io
This commit is contained in:
@@ -6,7 +6,8 @@ to drastically decrease the amount of single reads in the original source.
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
```kt
|
```kt
|
||||||
File("text.txt") // File
|
Path("text.txt") // Path
|
||||||
|
.getFile() // File
|
||||||
.openRead() // BatchSequence<Byte>
|
.openRead() // BatchSequence<Byte>
|
||||||
.batched(64) // BatchSequence<Byte>
|
.batched(64) // BatchSequence<Byte>
|
||||||
```
|
```
|
||||||
@@ -21,6 +22,7 @@ Example:
|
|||||||
val data = myData // Sequence<Byte>
|
val data = myData // Sequence<Byte>
|
||||||
.asBatch() // BatchSequence<Byte>
|
.asBatch() // BatchSequence<Byte>
|
||||||
|
|
||||||
File("text.txt")
|
Path("text.txt") // Path
|
||||||
|
.getOrCreateFile() // File
|
||||||
.write(data)
|
.write(data)
|
||||||
```
|
```
|
@@ -32,10 +32,10 @@ class Either<A, B> private constructor(
|
|||||||
if (isA) af(a!!.v) else bf(b!!.v)
|
if (isA) af(a!!.v) else bf(b!!.v)
|
||||||
|
|
||||||
fun <RA> mapA(transform: (A) -> RA): Either<RA, B> =
|
fun <RA> mapA(transform: (A) -> RA): Either<RA, B> =
|
||||||
Either(a.map(transform), b)
|
Either(a.mapNotNull(transform), b)
|
||||||
|
|
||||||
fun <RB> mapB(transform: (B) -> RB): Either<A, RB> =
|
fun <RB> mapB(transform: (B) -> RB): Either<A, RB> =
|
||||||
Either(a, b.map(transform))
|
Either(a, b.mapNotNull(transform))
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
if (isA) "Either<A>($a)"
|
if (isA) "Either<A>($a)"
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
package blitz
|
package blitz
|
||||||
|
|
||||||
|
import blitz.func.*
|
||||||
|
import blitz.func.io.*
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
// pureCat(args)
|
// pureCat(args)
|
||||||
// .impure()
|
// .impure()
|
||||||
|
8
src/main/kotlin/blitz/ModifyException.kt
Normal file
8
src/main/kotlin/blitz/ModifyException.kt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package blitz
|
||||||
|
|
||||||
|
fun <R> modifyException(new: Throwable, block: () -> R): R =
|
||||||
|
try {
|
||||||
|
block()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
throw new
|
||||||
|
}
|
4
src/main/kotlin/blitz/func/Multiples.kt
Normal file
4
src/main/kotlin/blitz/func/Multiples.kt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package blitz.func
|
||||||
|
|
||||||
|
infix fun <A, B, C> Pair<A, B>.tri(c: C): Triple<A, B, C> =
|
||||||
|
Triple(first, second, c)
|
@@ -14,3 +14,19 @@ fun <T> Sequence<Monad<T>>.rewrap(): Monad<Sequence<T>> =
|
|||||||
val iter = this@rewrap.iterator()
|
val iter = this@rewrap.iterator()
|
||||||
sequence { if (iter.hasNext()) yield(iter.next().impure()) }
|
sequence { if (iter.hasNext()) yield(iter.next().impure()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <A, B> Monad<Pair<A, B>>.rewrap(): Pair<Monad<A>, Monad<B>> {
|
||||||
|
val v = lazy { impure() }
|
||||||
|
return Monad { v.value.first } to Monad { v.value.second }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <A, B> Pair<Monad<A>, Monad<B>>.rewrap(): Monad<Pair<A, B>> =
|
||||||
|
Monad { first.impure() to second.impure() }
|
||||||
|
|
||||||
|
fun <A, B, C> Monad<Triple<A, B, C>>.rewrap(): Triple<Monad<A>, Monad<B>, Monad<C>> {
|
||||||
|
val v = lazy { impure() }
|
||||||
|
return Monad { v.value.first } to Monad { v.value.second } tri Monad { v.value.third }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <A, B, C> Triple<Monad<A>, Monad<B>, Monad<C>>.rewrap(): Monad<Triple<A, B, C>> =
|
||||||
|
Monad { first.impure() to second.impure() tri third.impure() }
|
@@ -1,13 +1,32 @@
|
|||||||
package blitz.func.io
|
package blitz.func.io
|
||||||
|
|
||||||
import blitz.func.Monad
|
import blitz.*
|
||||||
import blitz.func.bind
|
import blitz.func.*
|
||||||
import blitz.io.readerSequence
|
import blitz.io.*
|
||||||
import kotlinx.io.files.Path
|
|
||||||
import kotlinx.io.files.SystemFileSystem
|
|
||||||
|
|
||||||
fun Monad<String>.asPath() =
|
fun Monad<String>.asPath(): Monad<Path> =
|
||||||
bind { Path(it) }
|
bind { Path.of(it) }
|
||||||
|
|
||||||
fun Monad<Path>.read() =
|
fun Monad<Path>.read(): Monad<ByteBatchSequence> =
|
||||||
bind { p -> { SystemFileSystem.source(p) }.readerSequence() }
|
bind { it.getFile().read() }
|
||||||
|
|
||||||
|
fun Monad<Path>.write(seq: Monad<ByteBatchSequence>): Monad<Unit> =
|
||||||
|
bind { it.getFile().write(seq.impure()) }
|
||||||
|
|
||||||
|
fun Monad<Path>.append(seq: Monad<ByteBatchSequence>): Monad<Unit> =
|
||||||
|
bind { it.getFile().append(seq.impure()) }
|
||||||
|
|
||||||
|
fun Monad<ByteBatchSequence>.writeTo(path: Monad<Path>): Monad<Unit> =
|
||||||
|
path.write(this)
|
||||||
|
|
||||||
|
fun Monad<ByteBatchSequence>.appendTo(path: Monad<Path>): Monad<Unit> =
|
||||||
|
path.append(this)
|
||||||
|
|
||||||
|
fun Monad<Path>.exists(): Monad<Boolean> =
|
||||||
|
bind { it.exists() }
|
||||||
|
|
||||||
|
fun Monad<Path>.isDir(): Monad<Boolean> =
|
||||||
|
bind { it.isDir() }
|
||||||
|
|
||||||
|
fun Monad<Path>.isFile(): Monad<Boolean> =
|
||||||
|
bind { it.isFile() }
|
6
src/main/kotlin/blitz/io/Dir.kt
Normal file
6
src/main/kotlin/blitz/io/Dir.kt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package blitz.io
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class Dir internal constructor(
|
||||||
|
val path: Path
|
||||||
|
)
|
34
src/main/kotlin/blitz/io/File.kt
Normal file
34
src/main/kotlin/blitz/io/File.kt
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package blitz.io
|
||||||
|
|
||||||
|
import blitz.ByteBatchSequence
|
||||||
|
import kotlinx.io.Buffer
|
||||||
|
import kotlinx.io.files.SystemFileSystem
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class File internal constructor(
|
||||||
|
val path: Path
|
||||||
|
)
|
||||||
|
|
||||||
|
fun File.read(): ByteBatchSequence =
|
||||||
|
path.toKotlinxPath().let {
|
||||||
|
{ SystemFileSystem.source(it) }
|
||||||
|
}.readerSequence()
|
||||||
|
|
||||||
|
private fun File.writeAppendFrom(seq: ByteBatchSequence, append: Boolean) {
|
||||||
|
val path = path.toKotlinxPath()
|
||||||
|
SystemFileSystem.sink(path, append).use { sink ->
|
||||||
|
val iter = seq.iterator()
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
val batch = iter.nextBytes(8192)
|
||||||
|
val buff = Buffer()
|
||||||
|
buff.write(batch)
|
||||||
|
sink.write(buff, buff.size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun File.write(seq: ByteBatchSequence) =
|
||||||
|
writeAppendFrom(seq, false)
|
||||||
|
|
||||||
|
fun File.append(seq: ByteBatchSequence) =
|
||||||
|
writeAppendFrom(seq, true)
|
91
src/main/kotlin/blitz/io/Path.kt
Normal file
91
src/main/kotlin/blitz/io/Path.kt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package blitz.io
|
||||||
|
|
||||||
|
import blitz.modifyException
|
||||||
|
import kotlinx.io.files.SystemFileSystem
|
||||||
|
import kotlinx.io.files.SystemPathSeparator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every instance of this class represents an absolute path in a file system.
|
||||||
|
*/
|
||||||
|
@JvmInline
|
||||||
|
value class Path(
|
||||||
|
val parts: Array<String>
|
||||||
|
) {
|
||||||
|
val full: String
|
||||||
|
get() = parts.joinToString(separator.toString())
|
||||||
|
|
||||||
|
val name: String
|
||||||
|
get() = parts.last()
|
||||||
|
|
||||||
|
fun parent(): Path? =
|
||||||
|
if (parts.isEmpty()) null
|
||||||
|
else Path(parts.dropLast(1).toTypedArray())
|
||||||
|
|
||||||
|
// TODO: remove "." and ".." from the path
|
||||||
|
fun child(vararg paths: String): Path =
|
||||||
|
modifyException(Exception("children in Path.child() can not contain path separator!")) {
|
||||||
|
Path(parts + paths.onEach { assert(separator !in it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exists(): Boolean =
|
||||||
|
SystemFileSystem.exists(toKotlinxPath())
|
||||||
|
|
||||||
|
internal fun toKotlinxPath() =
|
||||||
|
kotlinx.io.files.Path("", *parts)
|
||||||
|
|
||||||
|
private fun kotlinxMeta() =
|
||||||
|
SystemFileSystem.metadataOrNull(toKotlinxPath())
|
||||||
|
|
||||||
|
fun isDir() =
|
||||||
|
kotlinxMeta()?.isDirectory ?: false
|
||||||
|
|
||||||
|
fun isFile() =
|
||||||
|
kotlinxMeta()?.isRegularFile ?: false
|
||||||
|
|
||||||
|
fun getDir(): Dir {
|
||||||
|
if (!exists()) throw Exception("Path does not exist!")
|
||||||
|
return Dir(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrCreateDir(): Dir {
|
||||||
|
if (!exists()) SystemFileSystem.createDirectories(toKotlinxPath())
|
||||||
|
return Dir(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFile(): File {
|
||||||
|
if (!exists()) throw Exception("Path does not exist!")
|
||||||
|
return File(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrCreateFile(): File {
|
||||||
|
if (!exists()) SystemFileSystem.sink(toKotlinxPath()).flush()
|
||||||
|
return File(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteFileOrDir() {
|
||||||
|
if (!exists()) throw Exception("Path does not exist!")
|
||||||
|
SystemFileSystem.delete(toKotlinxPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tryDeleteFileOrDir() {
|
||||||
|
try {
|
||||||
|
if (exists())
|
||||||
|
SystemFileSystem.delete(toKotlinxPath())
|
||||||
|
} catch (_: Exception) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val separator: Char = SystemPathSeparator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a path from a relative or absolute path string.
|
||||||
|
*/
|
||||||
|
fun of(path: String): Path {
|
||||||
|
if (path.isEmpty()) return Path(emptyArray())
|
||||||
|
val kx = kotlinx.io.files.Path(path)
|
||||||
|
if (kx.isAbsolute)
|
||||||
|
return Path(path.substring(1).split(separator).toTypedArray())
|
||||||
|
return of(SystemFileSystem.resolve(kx).toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user