From 488cd5a9394d46e9459e4864d298cc76b89a7f88 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 23 Feb 2021 17:40:28 +0300 Subject: [PATCH] Tables refactor to KType --- CHANGELOG.md | 1 + build.gradle.kts | 14 ++++---- dataforge-context/api/dataforge-context.api | 4 +++ dataforge-context/build.gradle.kts | 25 ++++++++++---- dataforge-data/build.gradle.kts | 4 +-- dataforge-io/build.gradle.kts | 4 +-- .../dataforge-io-yaml/build.gradle.kts | 4 +-- dataforge-meta/build.gradle.kts | 4 +-- dataforge-output/build.gradle.kts | 4 +-- dataforge-scripting/build.gradle.kts | 2 +- dataforge-tables/build.gradle.kts | 8 +++-- .../kotlin/hep/dataforge/tables/ColumnDef.kt | 4 +-- .../hep/dataforge/tables/ColumnHeader.kt | 6 ++-- .../hep/dataforge/tables/ColumnTable.kt | 4 +-- .../kotlin/hep/dataforge/tables/ListColumn.kt | 9 ++--- .../dataforge/tables/MutableColumnTable.kt | 2 +- .../hep/dataforge/tables/MutableTable.kt | 33 ++++++++++++------- .../kotlin/hep/dataforge/tables/RowTable.kt | 24 +++++++++----- .../kotlin/hep/dataforge/tables/Table.kt | 28 ++++++---------- .../dataforge/tables/TransformationColumn.kt | 23 ++++++++----- .../hep/dataforge/tables/io/TextRows.kt | 18 +++++----- .../dataforge/tables/io/textTableEnvelope.kt | 11 ++++--- .../hep/dataforge/tables/numericColumns.kt | 8 ++--- .../kotlin/hep/dataforge/tables/CastColumn.kt | 19 ++++++----- .../hep/dataforge/tables/io/TextRowsTest.kt | 23 ++++++------- dataforge-workspace/build.gradle.kts | 4 +-- gradle.properties | 16 +++++---- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle.kts | 14 ++++---- 29 files changed, 177 insertions(+), 145 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccbd72a1..82e3a927 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added ### Changed +- Kotlin-logging moved from common to JVM and JS. Replaced by console for native. ### Deprecated diff --git a/build.gradle.kts b/build.gradle.kts index 21633df0..478af371 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,20 +1,20 @@ plugins { - id("ru.mipt.npm.project") + id("ru.mipt.npm.gradle.project") } -val dataforgeVersion by extra("0.3.0") - - - allprojects { group = "hep.dataforge" - version = dataforgeVersion + version = "0.3.1" apply() } subprojects { - apply(plugin = "ru.mipt.npm.publish") + apply(plugin = "ru.mipt.npm.gradle.publish") + repositories{ + maven("https://dl.bintray.com/mipt-npm/kscience") + maven("https://dl.bintray.com/mipt-npm/dev") + } } readme { diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index d2d736d9..21ffb157 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -95,6 +95,10 @@ public final class hep/dataforge/context/Global : hep/dataforge/context/Context public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; } +public final class hep/dataforge/context/LoggingJvmKt { + public static final fun buildLogger (Lhep/dataforge/context/Context;Ljava/lang/String;)Lmu/KLogger; +} + public final class hep/dataforge/context/LoggingKt { public static final fun getLogger (Lhep/dataforge/context/Context;)Lmu/KLogger; public static final fun getLogger (Lhep/dataforge/context/ContextAware;)Lmu/KLogger; diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts index 84785ce8..3f80796e 100644 --- a/dataforge-context/build.gradle.kts +++ b/dataforge-context/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } description = "Context and provider definitions" @@ -11,22 +11,33 @@ kscience { kotlin { sourceSets { - val commonMain by getting { + val commonMain by getting{ dependencies { api(project(":dataforge-meta")) - api("io.github.microutils:kotlin-logging:1.9.0-dev-npm-2") } } - val jvmMain by getting { + jvmMain { dependencies { api(kotlin("reflect")) - api("ch.qos.logback:logback-classic:1.2.3") + api("io.github.microutils:kotlin-logging-jvm:2.0.4") + implementation("ch.qos.logback:logback-classic:1.2.3") } } - val jsMain by getting { + jsMain { dependencies { + api("io.github.microutils:kotlin-logging-js:2.0.4") } } +// +// val nativeMain by getting{ +// dependsOn(commonMain) +// } +// val mingwX64Main by getting{ +// dependsOn(nativeMain) +// } +// val linuxX64Main by getting{ +// dependsOn(nativeMain) +// } } } diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts index 16d98ced..74ed12db 100644 --- a/dataforge-data/build.gradle.kts +++ b/dataforge-data/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } kscience{ diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts index 01f749cb..c5292aec 100644 --- a/dataforge-io/build.gradle.kts +++ b/dataforge-io/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } description = "IO module" diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts index 4ee1029a..1b57fc71 100644 --- a/dataforge-io/dataforge-io-yaml/build.gradle.kts +++ b/dataforge-io/dataforge-io-yaml/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") -// id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") +// id("ru.mipt.npm.gradle.native") } description = "YAML meta IO" diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts index 45ca68f3..a2cc3c66 100644 --- a/dataforge-meta/build.gradle.kts +++ b/dataforge-meta/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } kscience { diff --git a/dataforge-output/build.gradle.kts b/dataforge-output/build.gradle.kts index 6051cb1c..7faac326 100644 --- a/dataforge-output/build.gradle.kts +++ b/dataforge-output/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } kotlin { diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts index e0c47057..a538a980 100644 --- a/dataforge-scripting/build.gradle.kts +++ b/dataforge-scripting/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("ru.mipt.npm.mpp") + id("ru.mipt.npm.gradle.mpp") } kotlin { diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts index d0f008c3..507b1f71 100644 --- a/dataforge-tables/build.gradle.kts +++ b/dataforge-tables/build.gradle.kts @@ -1,14 +1,16 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } kotlin { sourceSets { - val commonMain by getting{ + commonMain{ dependencies { api(project(":dataforge-context")) api(project(":dataforge-io")) + + api(kotlin("reflect")) } } } diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt index 2dd2e85b..a309443e 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnDef.kt @@ -1,10 +1,10 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta -import kotlin.reflect.KClass +import kotlin.reflect.KType public data class ColumnDef( override val name: String, - override val type: KClass, + override val type: KType, override val meta: Meta ): ColumnHeader \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt index 4aeb3124..95241682 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnHeader.kt @@ -6,7 +6,7 @@ import hep.dataforge.meta.int import hep.dataforge.meta.string import hep.dataforge.values.Value import hep.dataforge.values.ValueType -import kotlin.reflect.KClass +import kotlin.reflect.KType public typealias TableHeader = List> @@ -14,13 +14,13 @@ public typealias ValueTableHeader = List> public interface ColumnHeader { public val name: String - public val type: KClass + public val type: KType public val meta: Meta } public data class SimpleColumnHeader( override val name: String, - override val type: KClass, + override val type: KType, override val meta: Meta ) : ColumnHeader diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt index e79ebd08..c9c8ac97 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ColumnTable.kt @@ -13,11 +13,11 @@ public class ColumnTable(override val columns: Collection>) : override val rows: List> get() = (0 until rowsNum).map { VirtualRow(this, it) } - override fun getValue(row: Int, column: String): T? = columns[column]?.get(row) + override fun get(row: Int, column: String): T? = columns[column]?.get(row) } internal class VirtualRow(val table: Table, val index: Int) : Row { - override fun getValue(column: String): T? = table.getValue(index, column) + override fun get(column: String): T? = table.get(index, column) // override fun get(columnHeader: ColumnHeader): T? { // return table.co[columnHeader][index] diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt index 7b0549fa..165ff6de 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/ListColumn.kt @@ -1,12 +1,13 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta -import kotlin.reflect.KClass +import kotlin.reflect.KType +import kotlin.reflect.typeOf public class ListColumn( override val name: String, private val data: List, - override val type: KClass, + override val type: KType, override val meta: Meta ) : Column { override val size: Int get() = data.size @@ -18,7 +19,7 @@ public class ListColumn( name: String, def: ColumnScheme, data: List - ): ListColumn = ListColumn(name, data, T::class, def.toMeta()) + ): ListColumn = ListColumn(name, data, typeOf(), def.toMeta()) public inline operator fun invoke( name: String, @@ -31,5 +32,5 @@ public class ListColumn( public inline fun Column.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column { val data = List(size) { block(get(it)) } - return ListColumn(name, data, R::class, meta) + return ListColumn(name, data, typeOf(), meta) } \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt index eb69d7e7..01882902 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableColumnTable.kt @@ -11,7 +11,7 @@ public class MutableColumnTable(public val size: Int) : Table { VirtualRow(this, it) } - override fun getValue(row: Int, column: String): C? = columns[column]?.get(row) + override fun get(row: Int, column: String): C? = columns[column]?.get(row) /** * Add a fixed column to the end of the table diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt index f4070146..8fca7705 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/MutableTable.kt @@ -1,27 +1,36 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta -import hep.dataforge.meta.invoke import hep.dataforge.values.Value -import kotlin.reflect.KClass +import kotlin.properties.PropertyDelegateProvider +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KType +import kotlin.reflect.typeOf public class MutableTable( override val rows: MutableList>, - override val header: MutableList> -) : RowTable(rows, header) { + override val headers: MutableList>, +) : RowTable(rows, headers) { - public fun column(name: String, type: KClass, meta: Meta): ColumnHeader { - val column = SimpleColumnHeader(name, type, meta) - header.add(column) + @PublishedApi + internal fun addColumn(name: String, type: KType, meta: Meta): ColumnHeader { + val column = SimpleColumnHeader(name, type, meta) + headers.add(column) return column } - public inline fun column( + public inline fun addColumn( name: String, + noinline columnMetaBuilder: ColumnScheme.() -> Unit = {}, + ): ColumnHeader = addColumn(name, typeOf(), ColumnScheme(columnMetaBuilder).toMeta()) + + public inline fun column( noinline columnMetaBuilder: ColumnScheme.() -> Unit = {} - ): ColumnHeader { - return column(name, T::class, ColumnScheme(columnMetaBuilder).toMeta()) - } + ): PropertyDelegateProvider>> = + PropertyDelegateProvider { _, property -> + val res = addColumn(property.name, columnMetaBuilder) + ReadOnlyProperty { _, _ -> res } + } public fun row(map: Map): Row { val row = MapRow(map) @@ -37,5 +46,5 @@ public fun MutableTable.row(vararg pairs: Pair, Any?> row(pairs.associate { it.first.name to Value.of(it.second) }) public fun Table.edit(block: MutableTable.() -> Unit): Table { - return MutableTable(rows.toMutableList(), header.toMutableList()).apply(block) + return MutableTable(rows.toMutableList(), headers.toMutableList()).apply(block) } \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt index 9ea908cc..6b7b1261 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/RowTable.kt @@ -2,25 +2,31 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta import kotlinx.coroutines.flow.toList -import kotlin.reflect.KClass +import kotlin.reflect.KType public inline class MapRow(private val values: Map) : Row { - override fun getValue(column: String): C? = values[column] + override fun get(column: String): C? = values[column] } -internal class RowTableColumn(val table: Table, val header: ColumnHeader) : Column { +internal class RowTableColumn(val table: Table, val header: ColumnHeader) : Column { + init { + require(header in table.headers){"Header $header does not belong to $table"} + } + override val name: String get() = header.name - override val type: KClass get() = header.type + override val type: KType get() = header.type override val meta: Meta get() = header.meta override val size: Int get() = table.rows.size - override fun get(index: Int): T? = table.rows[index].getValue(name, type) + @Suppress("UNCHECKED_CAST") + override fun get(index: Int): R? = table[index, name]?.let { it as R} } -public open class RowTable(override val rows: List>, override val header: List>) : Table { - override fun getValue(row: Int, column: String): C? = rows[row].getValue(column) +public open class RowTable(override val rows: List>, override val headers: List>) : + Table { + override fun get(row: Int, column: String): C? = rows[row].get(column) - override val columns: List> get() = header.map { RowTableColumn(this, it) } + override val columns: List> get() = headers.map { RowTableColumn(this, it) } } -public suspend fun Rows.collect(): Table = this as? Table ?: RowTable(rowFlow().toList(), header) \ No newline at end of file +public suspend fun Rows.collect(): Table = this as? Table ?: RowTable(rowFlow().toList(), headers) \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt index 72875a05..bd0410e1 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/Table.kt @@ -2,22 +2,20 @@ package hep.dataforge.tables import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow -import kotlin.reflect.KClass -import kotlin.reflect.cast /** * Finite or infinite row set. Rows are produced in a lazy suspendable [Flow]. - * Each row must contain at least all the fields mentioned in [header]. + * Each row must contain at least all the fields mentioned in [headers]. */ public interface Rows { - public val header: TableHeader + public val headers: TableHeader public fun rowFlow(): Flow> } public interface Table : Rows { - public fun getValue(row: Int, column: String): T? + public operator fun get(row: Int, column: String): T? public val columns: Collection> - override val header: TableHeader get() = columns.toList() + override val headers: TableHeader get() = columns.toList() public val rows: List> override fun rowFlow(): Flow> = rows.asFlow() @@ -31,16 +29,13 @@ public interface Table : Rows { } } -public fun Table.getValue(row: Int, column: String, type: KClass): T? = - type.cast(getValue(row, column)) - public operator fun Collection>.get(name: String): Column? = find { it.name == name } -public inline operator fun Table.get(row: Int, column: String): T? = - getValue(row, column, T::class) -public operator fun Table.get(row: Int, column: ColumnHeader): T? = - getValue(row, column.name, column.type) +public inline operator fun Table.get(row: Int, column: ColumnHeader): R? { + require(headers.contains(column)) { "Column $column is not in table headers" } + return get(row, column.name) as? R +} public interface Column : ColumnHeader { public val size: Int @@ -56,10 +51,7 @@ public operator fun Column.iterator(): Iterator = iterator { } public interface Row { - public fun getValue(column: String): T? + public operator fun get(column: String): T? } -public fun Row.getValue(column: String, type: KClass): T? = type.cast(getValue(column)) - -public inline operator fun Row.get(column: String): T? = T::class.cast(getValue(column)) -public operator fun Row.get(column: ColumnHeader): T? = getValue(column.name, column.type) \ No newline at end of file +public inline operator fun Row.get(column: ColumnHeader): R? = get(column.name) as? R \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt index 83fdc06b..a0f78eea 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/TransformationColumn.kt @@ -1,17 +1,18 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta -import kotlin.reflect.KClass +import kotlin.reflect.KType +import kotlin.reflect.typeOf /** * A virtual column obtained by transforming Given row to a single value */ public class TransformationColumn( public val table: Table, - override val type: KClass, + override val type: KType, override val name: String, override val meta: Meta, - public val mapper: (Row) -> R? + public val mapper: (Row) -> R?, ) : Column { override val size: Int get() = table.rows.size @@ -25,10 +26,10 @@ public class TransformationColumn( */ public class CachedTransformationColumn( public val table: Table, - override val type: KClass, + override val type: KType, override val name: String, override val meta: Meta, - public val mapper: (Row) -> R? + public val mapper: (Row) -> R?, ) : Column { override val size: Int get() = table.rows.size private val values: HashMap = HashMap() @@ -42,14 +43,18 @@ public inline fun Table.mapRows( name: String, meta: Meta = Meta.EMPTY, cache: Boolean = false, - noinline mapper: (Row) -> R? + noinline mapper: (Row) -> R?, ): Column = if (cache) { - CachedTransformationColumn(this, R::class, name, meta, mapper) + CachedTransformationColumn(this, typeOf(), name, meta, mapper) } else { - TransformationColumn(this, R::class, name, meta, mapper) + TransformationColumn(this, typeOf(), name, meta, mapper) } -public fun Table.mapRowsToDouble(name: String, meta: Meta = Meta.EMPTY, block: (Row) -> Double): RealColumn { +public fun Table.mapRowsToDouble( + name: String, + meta: Meta = Meta.EMPTY, + block: (Row) -> Double, +): RealColumn { val data = DoubleArray(rows.size) { block(rows[it]) } return RealColumn(name, data, meta) } diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt index e9e6e31e..0ef003c4 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/TextRows.kt @@ -32,7 +32,7 @@ private fun readLine(header: ValueTableHeader, line: String): Row { * Finite or infinite [Rows] created from a fixed width text binary */ @ExperimentalIoApi -public class TextRows(override val header: ValueTableHeader, private val binary: Binary) : Rows { +public class TextRows(override val headers: ValueTableHeader, private val binary: Binary) : Rows { /** * A flow of indexes of string start offsets ignoring empty strings @@ -52,7 +52,7 @@ public class TextRows(override val header: ValueTableHeader, private val binary: flow { forEachUtf8Line { line -> if (line.isNotBlank()) { - val row = readLine(header, line) + val row = readLine(headers, line) emit(row) } } @@ -73,25 +73,25 @@ public suspend fun TextRows.buildRowIndex(): List = indexFlow().toList() */ @ExperimentalIoApi public class TextTable( - override val header: ValueTableHeader, + override val headers: ValueTableHeader, private val binary: Binary, public val index: List ) : Table { - override val columns: Collection> get() = header.map { RowTableColumn(this, it) } + override val columns: Collection> get() = headers.map { RowTableColumn(this, it) } override val rows: List> get() = index.map { readAt(it) } - override fun rowFlow(): Flow> = TextRows(header, binary).rowFlow() + override fun rowFlow(): Flow> = TextRows(headers, binary).rowFlow() private fun readAt(offset: Int): Row { return binary.read(offset) { val line = readUtf8Line() - return@read readLine(header, line) + return@read readLine(headers, line) } } - override fun getValue(row: Int, column: String): Value? { + override fun get(row: Int, column: String): Value? { val offset = index[row] return readAt(offset)[column] } @@ -132,11 +132,11 @@ private fun Output.writeValue(value: Value, width: Int, left: Boolean = true) { * Write rows without header to the output */ public suspend fun Output.writeRows(rows: Rows) { - val widths: List = rows.header.map { + val widths: List = rows.headers.map { it.textWidth } rows.rowFlow().collect { row -> - rows.header.forEachIndexed { index, columnHeader -> + rows.headers.forEachIndexed { index, columnHeader -> writeValue(row[columnHeader] ?: Null, widths[index]) } writeUtf8String("\r\n") diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt index b6be63e0..d0cca162 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/io/textTableEnvelope.kt @@ -10,12 +10,13 @@ import kotlinx.io.Binary import kotlinx.io.ByteArrayOutput import kotlinx.io.ExperimentalIoApi import kotlinx.io.asBinary +import kotlin.reflect.typeOf @ExperimentalIoApi -public suspend fun Table.wrap(): Envelope = Envelope { +public suspend fun Table.toEnvelope(): Envelope = Envelope { meta { - header.forEachIndexed { index, columnHeader -> + headers.forEachIndexed { index, columnHeader -> set("column", index.toString(), Meta { "name" put columnHeader.name if (!columnHeader.meta.isEmpty()) { @@ -26,9 +27,9 @@ public suspend fun Table.wrap(): Envelope = Envelope { } type = "table.value" - dataID = "valueTable[${this@wrap.hashCode()}]" + dataID = "valueTable[${this@toEnvelope.hashCode()}]" - data = ByteArrayOutput().apply { writeRows(this@wrap) }.toByteArray().asBinary() + data = ByteArrayOutput().apply { writeRows(this@toEnvelope) }.toByteArray().asBinary() } @DFExperimental @@ -37,7 +38,7 @@ public fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows { val header = envelope.meta.getIndexed("column") .entries.sortedBy { it.key?.toInt() } .map { (_, item) -> - SimpleColumnHeader(item.node["name"].string!!, Value::class, item.node["meta"].node ?: Meta.EMPTY) + SimpleColumnHeader(item.node["name"].string!!, typeOf(), item.node["meta"].node ?: Meta.EMPTY) } return TextRows(header, envelope.data ?: Binary.EMPTY) } \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt index 86868a22..05d26d49 100644 --- a/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt +++ b/dataforge-tables/src/commonMain/kotlin/hep/dataforge/tables/numericColumns.kt @@ -1,8 +1,8 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta -import hep.dataforge.meta.invoke -import kotlin.reflect.KClass +import kotlin.reflect.KType +import kotlin.reflect.typeOf public class RealColumn( @@ -10,7 +10,7 @@ public class RealColumn( public val data: DoubleArray, override val meta: Meta = Meta.EMPTY ) : Column { - override val type: KClass get() = Double::class + override val type: KType get() = typeOf() override val size: Int get() = data.size @@ -49,7 +49,7 @@ public class IntColumn( public val data: IntArray, override val meta: Meta = Meta.EMPTY ) : Column { - override val type: KClass get() = Int::class + override val type: KType get() = typeOf() override val size: Int get() = data.size diff --git a/dataforge-tables/src/jvmMain/kotlin/hep/dataforge/tables/CastColumn.kt b/dataforge-tables/src/jvmMain/kotlin/hep/dataforge/tables/CastColumn.kt index 0ab6c515..b9e62e96 100644 --- a/dataforge-tables/src/jvmMain/kotlin/hep/dataforge/tables/CastColumn.kt +++ b/dataforge-tables/src/jvmMain/kotlin/hep/dataforge/tables/CastColumn.kt @@ -2,30 +2,31 @@ package hep.dataforge.tables import hep.dataforge.meta.Meta import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KClass import kotlin.reflect.KProperty -import kotlin.reflect.full.isSubclassOf -import kotlin.reflect.safeCast +import kotlin.reflect.KType +import kotlin.reflect.full.isSubtypeOf @Suppress("UNCHECKED_CAST") -public fun Column<*>.cast(type: KClass): Column { - return if (type.isSubclassOf(this.type)) { +public fun Column<*>.cast(type: KType): Column { + return if (type.isSubtypeOf(this.type)) { this as Column } else { CastColumn(this, type) } } -public class CastColumn(private val origin: Column<*>, override val type: KClass) : Column { +private class CastColumn(private val origin: Column<*>, override val type: KType) : Column { override val name: String get() = origin.name override val meta: Meta get() = origin.meta override val size: Int get() = origin.size - - override fun get(index: Int): T? = type.safeCast(origin[index]) + @Suppress("UNCHECKED_CAST") + override fun get(index: Int): T? = origin[index]?.let { + it as T + } } -public class ColumnProperty(public val table: Table, public val type: KClass) : ReadOnlyProperty> { +public class ColumnProperty(public val table: Table, public val type: KType) : ReadOnlyProperty> { override fun getValue(thisRef: Any?, property: KProperty<*>): Column { val name = property.name return (table.columns[name] ?: error("Column with name $name not found in the table")).cast(type) diff --git a/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt b/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt index 90fa3a01..b03bec33 100644 --- a/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt +++ b/dataforge-tables/src/jvmTest/kotlin/hep/dataforge/tables/io/TextRowsTest.kt @@ -2,7 +2,6 @@ package hep.dataforge.tables.io import hep.dataforge.misc.DFExperimental import hep.dataforge.tables.Table -import hep.dataforge.tables.get import hep.dataforge.tables.row import hep.dataforge.values.Value import hep.dataforge.values.int @@ -19,22 +18,20 @@ import kotlin.test.assertEquals @ExperimentalIoApi class TextRowsTest { val table = Table { - val a = column("a") - val b = column("b") + val a by column() + val b by column() row(a to 1, b to "b1") row(a to 2, b to "b2") } @Test - fun testTableWriteRead() { - runBlocking { - val envelope = table.wrap() - val string = envelope.data!!.toByteArray().decodeToString() - println(string) - val table = TextRows.readEnvelope(envelope) - val rows = table.rowFlow().toList() - assertEquals(1, rows[0]["a"]?.int) - assertEquals("b2", rows[1]["b"]?.string) - } + fun testTableWriteRead() = runBlocking { + val envelope = table.toEnvelope() + val string = envelope.data!!.toByteArray().decodeToString() + println(string) + val table = TextRows.readEnvelope(envelope) + val rows = table.rowFlow().toList() + assertEquals(1, rows[0]["a"]?.int) + assertEquals("b2", rows[1]["b"]?.string) } } \ No newline at end of file diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts index ae83b062..c6e62b36 100644 --- a/dataforge-workspace/build.gradle.kts +++ b/dataforge-workspace/build.gradle.kts @@ -1,6 +1,6 @@ plugins { - id("ru.mipt.npm.mpp") - id("ru.mipt.npm.native") + id("ru.mipt.npm.gradle.mpp") + id("ru.mipt.npm.gradle.native") } kotlin { diff --git a/gradle.properties b/gradle.properties index a782b701..9b6d2aef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,11 @@ -kotlin.code.style=official -kotlin.parallel.tasks.in.project=true -kotlin.mpp.enableGranularSourceSetsMetadata=true -//kotlin.native.enableDependencyPropagation=false -kotlin.mpp.stability.nowarn=true - org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m org.gradle.parallel=true -systemProp.org.gradle.internal.publish.checksums.insecure=true \ No newline at end of file + +kotlin.code.style=official +kotlin.parallel.tasks.in.project=true + +kotlin.mpp.enableGranularSourceSetsMetadata=true +kotlin.native.enableDependencyPropagation=false +kotlin.mpp.stability.nowarn=true + +bintrayPublish=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 28ff446a..442d9132 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index defbc0e5..8746a320 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,6 @@ pluginManagement { repositories { - mavenLocal() + maven("https://repo.kotlin.link") jcenter() gradlePluginPortal() maven("https://dl.bintray.com/kotlin/kotlin-eap") @@ -10,15 +10,15 @@ pluginManagement { maven("https://dl.bintray.com/mipt-npm/dev") } - val toolsVersion = "0.7.6" + val toolsVersion = "0.8.3" val kotlinVersion = "1.4.30" plugins { - id("ru.mipt.npm.project") version toolsVersion - id("ru.mipt.npm.mpp") version toolsVersion - id("ru.mipt.npm.jvm") version toolsVersion - id("ru.mipt.npm.js") version toolsVersion - id("ru.mipt.npm.publish") version toolsVersion + id("ru.mipt.npm.gradle.project") version toolsVersion + id("ru.mipt.npm.gradle.mpp") version toolsVersion + id("ru.mipt.npm.gradle.jvm") version toolsVersion + id("ru.mipt.npm.gradle.js") version toolsVersion + id("ru.mipt.npm.gradle.publish") version toolsVersion kotlin("jvm") version kotlinVersion kotlin("js") version kotlinVersion }