IO update
This commit is contained in:
parent
4cafac1f1b
commit
2d8810110e
@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
val kotlinVersion: String by rootProject.extra("1.3.20")
|
val kotlinVersion: String by rootProject.extra("1.3.20")
|
||||||
val ioVersion: String by rootProject.extra("0.1.2")
|
val ioVersion: String by rootProject.extra("0.1.4")
|
||||||
val coroutinesVersion: String by rootProject.extra("1.1.1")
|
val coroutinesVersion: String by rootProject.extra("1.1.1")
|
||||||
val serializationVersion: String by rootProject.extra("0.9.1")
|
val serializationVersion: String by rootProject.extra("0.9.1")
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import hep.dataforge.meta.*
|
|||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.provider.Provider
|
import hep.dataforge.provider.Provider
|
||||||
|
import hep.dataforge.provider.Types
|
||||||
import hep.dataforge.provider.provideAll
|
import hep.dataforge.provider.provideAll
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -94,8 +95,8 @@ interface Context : Named, MetaRepr, Provider, CoroutineScope {
|
|||||||
/**
|
/**
|
||||||
* A sequences of all objects provided by plugins with given target and type
|
* A sequences of all objects provided by plugins with given target and type
|
||||||
*/
|
*/
|
||||||
inline fun <reified T : Any> Context.list(target: String): Sequence<T> {
|
inline fun <reified T : Any> Context.provideAll(target: String = Types[T::class]): Sequence<T> {
|
||||||
return plugins.asSequence().flatMap { provideAll(target) }.mapNotNull { it as? T }
|
return plugins.asSequence().flatMap { it.provideAll(target) }.filterIsInstance<T>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +44,8 @@ data class PluginTag(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
const val DATAFORGE_GROUP = "hep.dataforge"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build new PluginTag from standard string representation
|
* Build new PluginTag from standard string representation
|
||||||
*
|
*
|
||||||
|
@ -85,5 +85,13 @@ inline fun <reified T : Any> Provider.provide(target: String, name: String): T?
|
|||||||
* [Sequence] of all elements with given target
|
* [Sequence] of all elements with given target
|
||||||
*/
|
*/
|
||||||
fun Provider.provideAll(target: String): Sequence<Any> {
|
fun Provider.provideAll(target: String): Sequence<Any> {
|
||||||
return listTop(target).map { it -> provideTop(target, it) ?: error("The element $it is declared but not provided") }
|
return listTop(target).map { provideTop(target, it) ?: error("The element $it is declared but not provided") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide an object with given name inferring target from its type using [Type] annotation
|
||||||
|
*/
|
||||||
|
inline fun <reified T : Any> Provider.provideByType(name: String): T? {
|
||||||
|
val target = Types[T::class]
|
||||||
|
return provide(target, name)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package hep.dataforge.provider
|
||||||
|
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A text label for internal DataForge type classification. Alternative for mime container type.
|
||||||
|
*
|
||||||
|
* The DataForge type notation presumes that type `A.B.C` is the subtype of `A.B`
|
||||||
|
*/
|
||||||
|
@MustBeDocumented
|
||||||
|
@Target(AnnotationTarget.CLASS)
|
||||||
|
annotation class Type(val id: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utils to get type of classes and objects
|
||||||
|
*/
|
||||||
|
object Types {
|
||||||
|
operator fun get(cl: KClass<*>): String {
|
||||||
|
return cl.annotations.filterIsInstance<Type>().firstOrNull()?.id ?: cl.simpleName ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun get(obj: Any): String {
|
||||||
|
return get(obj::class)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("org.jetbrains.kotlin.multiplatform")
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
targets {
|
|
||||||
fromPreset(presets.jvm, 'jvm')
|
|
||||||
fromPreset(presets.js, 'js')
|
|
||||||
// For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64
|
|
||||||
// For Linux, preset should be changed to e.g. presets.linuxX64
|
|
||||||
// For MacOS, preset should be changed to e.g. presets.macosX64
|
|
||||||
//fromPreset(presets.iosX64, 'ios')
|
|
||||||
}
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
api project(":dataforge-context")
|
|
||||||
api project(":dataforge-meta-io")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jvmMain {
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
20
dataforge-io/build.gradle.kts
Normal file
20
dataforge-io/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
plugins {
|
||||||
|
kotlin("multiplatform")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
jvm()
|
||||||
|
js()
|
||||||
|
sourceSets {
|
||||||
|
val commonMain by getting{
|
||||||
|
dependencies {
|
||||||
|
api(project(":dataforge-context"))
|
||||||
|
api(project(":dataforge-meta-io"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
package hep.dataforge.io
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.context.AbstractPlugin
|
||||||
import hep.dataforge.context.Plugin
|
import hep.dataforge.context.Plugin
|
||||||
|
import hep.dataforge.context.PluginTag
|
||||||
|
import hep.dataforge.context.PluginTag.Companion.DATAFORGE_GROUP
|
||||||
import hep.dataforge.meta.EmptyMeta
|
import hep.dataforge.meta.EmptyMeta
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.names.EmptyName
|
import hep.dataforge.names.EmptyName
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,3 +42,22 @@ inline fun <reified T : Any> OutputManager.typed(
|
|||||||
): Output<T> {
|
): Output<T> {
|
||||||
return typed(T::class, name, stage, meta)
|
return typed(T::class, name, stage, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System console output.
|
||||||
|
* The [ConsoleOutput] is used when no other [OutputManager] is provided.
|
||||||
|
*/
|
||||||
|
expect val ConsoleOutput: Output<Any>
|
||||||
|
|
||||||
|
object ConsoleOutputManager : AbstractPlugin(), OutputManager {
|
||||||
|
override val tag: PluginTag = PluginTag("output.console", group = DATAFORGE_GROUP)
|
||||||
|
|
||||||
|
override fun get(name: Name, stage: Name, meta: Meta): Output<Any> = ConsoleOutput
|
||||||
|
|
||||||
|
override fun <T : Any> typed(type: KClass<T>, name: Name, stage: Name, meta: Meta): Output<T> = ConsoleOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dispatcher for output tasks.
|
||||||
|
*/
|
||||||
|
expect val OutputDispatcher : CoroutineDispatcher
|
@ -0,0 +1,59 @@
|
|||||||
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.context.provideAll
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
class TextOutput(override val context: Context, private val output: kotlinx.io.core.Output) : Output<Any> {
|
||||||
|
private val cache = HashMap<KClass<*>, TextRenderer>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the first [TextRenderer] matching the given object type.
|
||||||
|
*/
|
||||||
|
override fun render(obj: Any, meta: Meta) {
|
||||||
|
val renderer: TextRenderer = if (obj is CharSequence) {
|
||||||
|
DefaultTextRenderer
|
||||||
|
} else {
|
||||||
|
val value = cache[obj::class]
|
||||||
|
if (value == null) {
|
||||||
|
val answer = context.provideAll<TextRenderer>().filter { it.type.isInstance(obj) }.firstOrNull()
|
||||||
|
if (answer != null) {
|
||||||
|
cache[obj::class] = answer
|
||||||
|
answer
|
||||||
|
} else {
|
||||||
|
DefaultTextRenderer
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.launch(OutputDispatcher) {
|
||||||
|
renderer.run { output.render(obj) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TextRenderer {
|
||||||
|
/**
|
||||||
|
* The priority of this renderer compared to other renderers
|
||||||
|
*/
|
||||||
|
val priority: Int
|
||||||
|
/**
|
||||||
|
* The type of the content served by this renderer
|
||||||
|
*/
|
||||||
|
val type: KClass<*>
|
||||||
|
|
||||||
|
suspend fun kotlinx.io.core.Output.render(obj: Any)
|
||||||
|
}
|
||||||
|
|
||||||
|
object DefaultTextRenderer : TextRenderer {
|
||||||
|
override val priority: Int = Int.MAX_VALUE
|
||||||
|
override val type: KClass<*> = Any::class
|
||||||
|
|
||||||
|
override suspend fun kotlinx.io.core.Output.render(obj: Any) {
|
||||||
|
append(obj.toString())
|
||||||
|
append('\n')
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.context.Context
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System console output.
|
||||||
|
* The [ConsoleOutput] is used when no other [OutputManager] is provided.
|
||||||
|
*/
|
||||||
|
actual val ConsoleOutput: Output<Any> = object : Output<Any> {
|
||||||
|
override fun render(obj: Any, meta: Meta) {
|
||||||
|
println(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val context: Context get() = Global
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
actual val OutputDispatcher: CoroutineDispatcher = Dispatchers.Default
|
@ -0,0 +1,13 @@
|
|||||||
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.context.Global
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.io.streams.asOutput
|
||||||
|
|
||||||
|
/**
|
||||||
|
* System console output.
|
||||||
|
* The [ConsoleOutput] is used when no other [OutputManager] is provided.
|
||||||
|
*/
|
||||||
|
actual val ConsoleOutput: Output<Any> = TextOutput(Global, System.out.asOutput())
|
||||||
|
|
||||||
|
actual val OutputDispatcher = Dispatchers.IO
|
@ -1,16 +0,0 @@
|
|||||||
package hep.dataforge.io
|
|
||||||
|
|
||||||
import hep.dataforge.context.Context
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
class TextOutput(override val context: Context, private val output: kotlinx.io.core.Output) : Output<Any> {
|
|
||||||
override fun render(obj: Any, meta: Meta) {
|
|
||||||
context.launch(Dispatchers.IO) {
|
|
||||||
output.append(obj.toString())
|
|
||||||
output.append('\n')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user