IO update
This commit is contained in:
parent
4cafac1f1b
commit
2d8810110e
@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
|
||||
buildscript {
|
||||
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 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.toName
|
||||
import hep.dataforge.provider.Provider
|
||||
import hep.dataforge.provider.Types
|
||||
import hep.dataforge.provider.provideAll
|
||||
import hep.dataforge.values.Value
|
||||
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
|
||||
*/
|
||||
inline fun <reified T : Any> Context.list(target: String): Sequence<T> {
|
||||
return plugins.asSequence().flatMap { provideAll(target) }.mapNotNull { it as? T }
|
||||
inline fun <reified T : Any> Context.provideAll(target: String = Types[T::class]): Sequence<T> {
|
||||
return plugins.asSequence().flatMap { it.provideAll(target) }.filterIsInstance<T>()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +44,8 @@ data class PluginTag(
|
||||
|
||||
companion object {
|
||||
|
||||
const val DATAFORGE_GROUP = "hep.dataforge"
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
|
||||
import hep.dataforge.context.AbstractPlugin
|
||||
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.Meta
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
@ -38,3 +42,22 @@ inline fun <reified T : Any> OutputManager.typed(
|
||||
): Output<T> {
|
||||
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