Skip to content

Commit a05fd68

Browse files
committed
jsoizo#157, jsoizo#133. Replace Java io with kotlinx-io. Move to common code. Add wasmJs target.
1 parent 45dc338 commit a05fd68

33 files changed

+841
-1185
lines changed

build.gradle.kts

+22-3
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ plugins {
88
alias(libs.plugins.dokka)
99
alias(libs.plugins.kover)
1010
alias(libs.plugins.mavenPublish)
11+
alias(libs.plugins.kotest)
1112
}
1213

1314
group = "com.jsoizo"
14-
version = "1.10.0"
15+
version = "2.0.0-dev1"
1516
val projectName = "kotlin-csv"
1617

1718
buildscript {
@@ -36,12 +37,30 @@ kotlin {
3637
nodejs {
3738
}
3839
}
40+
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
41+
wasmJs {
42+
browser()
43+
nodejs()
44+
}
3945
sourceSets {
40-
commonMain {}
46+
commonMain {
47+
dependencies {
48+
implementation(libs.kotlinx.coroutines.core)
49+
api(libs.kotlinx.io)
50+
}
51+
}
4152
commonTest {
4253
dependencies {
4354
implementation(kotlin("test-common"))
4455
implementation(kotlin("test-annotations-common"))
56+
implementation(libs.kotest.framework.engine)
57+
implementation(libs.kotlinx.datetime)
58+
}
59+
}
60+
61+
wasmJsTest {
62+
dependencies {
63+
implementation(kotlin("test-wasm-js"))
4564
}
4665
}
4766

@@ -118,4 +137,4 @@ mavenPublishing {
118137
}
119138
}
120139
}
121-
}
140+
}

gradle.properties

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
kotlin.code.style=official
1+
kotlin.code.style=official
2+
org.gradle.jvmargs=-Xmx4096m

gradle/libs.versions.toml

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[versions]
22
kotlin = "2.1.0"
3+
kotlinx-io = "0.6.0"
34
coroutines = "1.10.1"
45
maven-publish = "0.30.0"
56
kover = "0.8.2"
@@ -9,8 +10,11 @@ kotest = "5.9.1"
910
[libraries]
1011
#kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
1112
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
13+
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version = "0.6.1" }
14+
kotlinx-io = { module = "org.jetbrains.kotlinx:kotlinx-io-core", version.ref = "kotlinx-io" }
1215
kotest-runner-junit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
1316
kotest-assertions-core = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" }
17+
kotest-framework-engine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" }
1418

1519
[bundles]
1620
kotest = ["kotest-runner-junit5", "kotest-assertions-core"]
@@ -20,3 +24,4 @@ kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref =
2024
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
2125
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
2226
mavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "maven-publish" }
27+
kotest = { id = "io.kotest.multiplatform", version.ref = "kotest" }
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,110 @@
11
package com.jsoizo.kotlincsv.client
22

3-
import com.jsoizo.kotlincsv.dsl.context.CsvReaderContext
3+
import com.jsoizo.kotlincsv.dsl.CsvReaderScope
4+
import com.jsoizo.kotlincsv.dsl.context.ICsvReaderContext
5+
import kotlinx.io.Source
6+
import kotlinx.io.files.Path
47

5-
/**
6-
* CSV Reader class
7-
*
8-
* @author doyaaaaaken
9-
*/
10-
expect class CsvReader(
11-
ctx: CsvReaderContext = CsvReaderContext()
12-
) {
8+
interface CsvReader : ICsvReaderContext {
139
/**
1410
* read csv data as String, and convert into List<List<String>>
1511
*/
1612
fun readAll(data: String): List<List<String>>
1713

14+
/**
15+
* read csv data from a Source, and convert into List<List<String>>.
16+
*/
17+
fun readAll(data: Source): List<List<String>>
18+
19+
/**
20+
* read csv data from a Path, and convert into List<List<String>>
21+
*
22+
* No need to close the [path] when calling this method.
23+
*/
24+
fun readAll(path: Path): List<List<String>>
25+
1826
/**
1927
* read csv data with header, and convert into List<Map<String, String>>
2028
*/
2129
fun readAllWithHeader(data: String): List<Map<String, String>>
30+
31+
/**
32+
* read csv data with a header from a Source, and convert into List<List<String>>.
33+
*/
34+
fun readAllWithHeader(data: Source): List<Map<String, String>>
35+
36+
/**
37+
* read csv data with header, and convert into List<Map<String, String>>
38+
*
39+
* No need to close [path] when calling this method.
40+
*/
41+
fun readAllWithHeader(path: Path): List<Map<String, String>>
42+
43+
/**
44+
* open [source] and execute reading process.
45+
*
46+
* If you want to control read flow precisely, use this method.
47+
* Otherwise, use utility method (e.g. CsvReader.readAll ).
48+
*
49+
* Usage example:
50+
* <pre>
51+
* val data: Sequence<List<String?>> = csvReader().open(source) {
52+
* readAllAsSequence()
53+
* .map { fields -> fields.map { it.trim() } }
54+
* .map { fields -> fields.map { if(it.isBlank()) null else it } }
55+
* }
56+
* </pre>
57+
*/
58+
fun <T> open(source: Source, read: CsvReaderScope.() -> T): T
59+
60+
/**
61+
* open [path] and execute reading process.
62+
*
63+
* If you want to control read flow precisely, use this method.
64+
* Otherwise, use utility method (e.g. CsvReader.readAll ).
65+
*
66+
* Usage example:
67+
* <pre>
68+
* val data: Sequence<List<String?>> = csvReader().open("test.csv") {
69+
* readAllAsSequence()
70+
* .map { fields -> fields.map { it.trim() } }
71+
* .map { fields -> fields.map { if(it.isBlank()) null else it } }
72+
* }
73+
* </pre>
74+
*/
75+
fun <T> open(path: Path, read: CsvReaderScope.() -> T): T
76+
77+
/**
78+
* open [source] and execute reading process on a **suspending** function.
79+
*
80+
* If you want to control read flow precisely, use this method.
81+
* Otherwise, use utility method (e.g. CsvReader.readAll ).
82+
*
83+
* Usage example:
84+
* <pre>
85+
* val data: Sequence<List<String?>> = csvReader().open(source) {
86+
* readAllAsSequence()
87+
* .map { fields -> fields.map { it.trim() } }
88+
* .map { fields -> fields.map { if(it.isBlank()) null else it } }
89+
* }
90+
* </pre>
91+
*/
92+
suspend fun <T> openAsync(source: Source, read: suspend CsvReaderScope.() -> T): T
93+
94+
/**
95+
* open [path] and execute reading process on a **suspending** function.
96+
*
97+
* If you want to control read flow precisely, use this method.
98+
* Otherwise, use utility method (e.g. CsvReader.readAll ).
99+
*
100+
* Usage example:
101+
* <pre>
102+
* val data: Sequence<List<String?>> = csvReader().openAsync("test.csv") {
103+
* readAllAsSequence()
104+
* .map { fields -> fields.map { it.trim() } }
105+
* .map { fields -> fields.map { if(it.isBlank()) null else it } }
106+
* }
107+
* </pre>
108+
*/
109+
suspend fun <T> openAsync(path: Path, read: suspend CsvReaderScope.() -> T): T
22110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package com.jsoizo.kotlincsv.client
2+
3+
import com.jsoizo.kotlincsv.dsl.CsvReaderScope
4+
import com.jsoizo.kotlincsv.dsl.context.CsvReaderContext
5+
import com.jsoizo.kotlincsv.dsl.context.ICsvReaderContext
6+
import kotlinx.io.Buffer
7+
import kotlinx.io.Source
8+
import kotlinx.io.buffered
9+
import kotlinx.io.files.Path
10+
import kotlinx.io.files.SystemFileSystem
11+
12+
/**
13+
* CSVReader implementation.
14+
*
15+
* @author gsteckman
16+
*/
17+
internal class CsvReaderImpl(
18+
private val ctx: CsvReaderContext = CsvReaderContext()
19+
) : CsvReader, ICsvReaderContext by ctx {
20+
override fun readAll(data: String): List<List<String>> = data.csvReadAll(ctx)
21+
22+
override fun readAll(data: Source): List<List<String>> = data.csvReadAll(ctx)
23+
24+
override fun readAll(path: Path): List<List<String>> = path.csvReadAll(ctx)
25+
26+
override fun readAllWithHeader(data: String): List<Map<String, String>> =
27+
data.csvReadAllWithHeader(ctx)
28+
29+
override fun readAllWithHeader(data: Source): List<Map<String, String>> = data.csvReadAllWithHeader(ctx)
30+
31+
override fun readAllWithHeader(path: Path): List<Map<String, String>> = path.csvReadAllWithHeader(ctx)
32+
33+
override fun <T> open(source: Source, read: CsvReaderScope.() -> T): T =
34+
SourceCsvReaderScope(ctx, source, ctx.logger).read()
35+
36+
override fun <T> open(path: Path, read: CsvReaderScope.() -> T): T =
37+
SystemFileSystem.source(path).buffered().use {
38+
return open(it, read)
39+
}
40+
41+
override suspend fun <T> openAsync(source: Source, read: suspend CsvReaderScope.() -> T): T =
42+
SourceCsvReaderScope(ctx, source, ctx.logger).read()
43+
44+
override suspend fun <T> openAsync(path: Path, read: suspend CsvReaderScope.() -> T): T =
45+
SystemFileSystem.source(path).buffered().use {
46+
return openAsync(it, read)
47+
}
48+
}
49+
50+
/**
51+
* read csv data as String, and convert into List<List<String>>
52+
*/
53+
fun String.csvReadAll(ctx: CsvReaderContext = CsvReaderContext()): List<List<String>> =
54+
Buffer().apply{ write(encodeToByteArray()) }.use {
55+
it.csvReadAll(ctx)
56+
}
57+
58+
/**
59+
* read csv data with header, and convert into List<Map<String, String>>
60+
*/
61+
fun String.csvReadAllWithHeader(ctx: CsvReaderContext = CsvReaderContext()): List<Map<String, String>> =
62+
Buffer().apply{ write(encodeToByteArray()) }.use {
63+
it.csvReadAllWithHeader(ctx)
64+
}
65+
66+
/**
67+
* read csv data from a Source, and convert into List<List<String>>.
68+
*/
69+
fun Source.csvReadAll(ctx: CsvReaderContext = CsvReaderContext()): List<List<String>> =
70+
SourceCsvReaderScope(ctx, this, ctx.logger).readAllAsSequence().toList()
71+
72+
/**
73+
* read csv data from a Path, and convert into List<List<String>>.
74+
*
75+
* No need to close the Path when calling this method.
76+
*/
77+
fun Path.csvReadAll(ctx: CsvReaderContext = CsvReaderContext()): List<List<String>> =
78+
SystemFileSystem.source(this).buffered().use {
79+
return it.csvReadAll(ctx)
80+
}
81+
82+
/**
83+
* read csv data with a header from a Source, and convert into List<List<String>>.
84+
*/
85+
fun Source.csvReadAllWithHeader(ctx: CsvReaderContext = CsvReaderContext()): List<Map<String, String>> =
86+
SourceCsvReaderScope(ctx, this, ctx.logger).readAllWithHeaderAsSequence().toList()
87+
88+
/**
89+
* read csv data with header, and convert into List<Map<String, String>>
90+
*
91+
* No need to close Path when calling this method.
92+
*/
93+
fun Path.csvReadAllWithHeader(ctx: CsvReaderContext = CsvReaderContext()): List<Map<String, String>> =
94+
SystemFileSystem.source(this).buffered().use {
95+
return it.csvReadAllWithHeader(ctx)
96+
}
97+
98+
/**
99+
* read all csv rows as Sequence
100+
*/
101+
fun Source.csvReadAllAsSequence(fieldsNum: Int? = null, ctx: CsvReaderContext = CsvReaderContext())
102+
: Sequence<List<String>> = SourceCsvReaderScope(ctx, this, ctx.logger).readAllAsSequence(fieldsNum)
103+
104+
/**
105+
* read all csv rows as Sequence with header information
106+
*/
107+
fun Source.csvReadAllWithHeaderAsSequence(ctx: CsvReaderContext = CsvReaderContext())
108+
: Sequence<Map<String, String>> = SourceCsvReaderScope(ctx, this, ctx.logger).readAllWithHeaderAsSequence()
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
package com.jsoizo.kotlincsv.client
22

3-
import com.jsoizo.kotlincsv.dsl.context.CsvWriterContext
3+
import com.jsoizo.kotlincsv.dsl.CsvWriterScope
4+
import com.jsoizo.kotlincsv.dsl.context.ICsvWriterContext
5+
import kotlinx.io.Sink
6+
import kotlinx.io.files.Path
47

5-
/**
6-
* CSV Writer class
7-
*
8-
* @author doyaaaaaken
9-
*/
10-
expect class CsvWriter(ctx: CsvWriterContext = CsvWriterContext()) {
8+
interface CsvWriter : ICsvWriterContext {
9+
fun writeAll(rows: List<List<Any?>>, sink: Sink, append: Boolean = false)
1110

12-
fun open(targetFileName: String, append: Boolean = false, write: ICsvFileWriter.() -> Unit)
11+
fun writeAll(rows: List<List<Any?>>, path: Path, append: Boolean = false)
1312

14-
fun writeAll(rows: List<List<Any?>>, targetFileName: String, append: Boolean = false)
13+
suspend fun writeAllAsync(rows: List<List<Any?>>, sink: Sink, append: Boolean = false)
1514

16-
suspend fun writeAllAsync(rows: List<List<Any?>>, targetFileName: String, append: Boolean = false)
15+
suspend fun writeAllAsync(rows: List<List<Any?>>, path: Path, append: Boolean = false)
1716

18-
suspend fun openAsync(targetFileName: String, append: Boolean = false, write: suspend ICsvFileWriter.() -> Unit)
17+
fun open(sink: Sink, append: Boolean = false, write: CsvWriterScope.() -> Unit)
18+
19+
fun open(path: Path, append: Boolean = false, write: CsvWriterScope.() -> Unit)
20+
21+
suspend fun openAsync(sink: Sink, append: Boolean = false, write: suspend CsvWriterScope.() -> Unit)
22+
23+
suspend fun openAsync(path: Path, append: Boolean = false, write: suspend CsvWriterScope.() -> Unit)
1924
}

0 commit comments

Comments
 (0)