Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
Works on already exist configs
Browse files Browse the repository at this point in the history
  • Loading branch information
reosfire committed May 12, 2024
1 parent 122cf57 commit 436e009
Show file tree
Hide file tree
Showing 33 changed files with 674 additions and 328 deletions.
12 changes: 8 additions & 4 deletions .run/Run server.run.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run server" type="Application" factoryName="Application" focusToolWindowBeforeRun="true">
<envs>
<env name="CFGA" value="110" />
<env name="CFGC_LI" value="2" />
<env name="CFGC_LI_[0]" value="111" />
<env name="CFGC_LI_[1]" value="222" />
<env name="DAYLIFECRAFT_SETTINGS_SERVER_ENV" value="DEV" />
</envs>
<option name="MAIN_CLASS_NAME" value="com.daylifecraft.minigames.Init" />
<module name="minigames.runner.main" />
<selectedOptions>
<option name="environmentVariables" visible="false" />
</selectedOptions>
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/runner" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
</component>
127 changes: 127 additions & 0 deletions common/src/main/kotlin/com/daylifecraft/common/config/Config.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package com.daylifecraft.common.config

import com.daylifecraft.common.config.providers.Provider
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.jvmErasure

inline fun <reified T: Any> load(
firstLoader: Provider,
vararg loaders: Provider,
basePath: ConfigPath = ConfigPath(),
): T {
val l = mutableListOf(firstLoader)
l.addAll(loaders)
return load(T::class, basePath, l)
}

fun <T: Any> load(
kClass: KClass<T>,
basePath: ConfigPath,
loaders: List<Provider>
): T {
if (!kClass.isData) throw IllegalArgumentException("T must be data class, but was ${kClass.simpleName}")

val primaryConstructor = kClass.primaryConstructor ?: throw IllegalArgumentException("Primary constructor of data class not found!?")

val arguments = mutableMapOf<KParameter, Any?>()

for (constructorParameter in primaryConstructor.parameters) {
basePath.addLast(StringToken(constructorParameter.name!!))

val res = when (constructorParameter.type.jvmErasure) {
Int::class -> loaders.tryGet { int(basePath) }
Long::class -> loaders.tryGet { long(basePath) }
Float::class -> loaders.tryGet { float(basePath) }
Double::class -> loaders.tryGet { double(basePath) }
Boolean::class -> loaders.tryGet { boolean(basePath) }
String::class -> loaders.tryGet { string(basePath) }
List::class -> {
loadList(loaders, basePath, constructorParameter.type.arguments[0].type!!.jvmErasure)
}
else -> load(constructorParameter.type.jvmErasure, basePath, loaders)
}
basePath.removeLast()

if (res == null) {
if (constructorParameter.isOptional) continue
if (!constructorParameter.type.isMarkedNullable) error("Not found argument for non-nullable constructor parameter: ${constructorParameter.name} On path: $basePath")
}

arguments[constructorParameter] = res
}

try {
return primaryConstructor.callBy(arguments)
} catch (e: Exception) {
throw RuntimeException("Failed to instantiate class ${kClass.simpleName}. On path: $basePath", e)
}
}

private fun loadList(
loaders: List<Provider>,
basePath: ConfigPath,
listElementType: KClass<*>,
): List<Any> {
val listSize = loaders.tryGet { listSize(basePath) } ?: 0
return when (listElementType) {
String::class -> loadList(listSize, basePath) {
loaders.tryGet { string(basePath) }
}

Int::class -> loadList(listSize, basePath) {
loaders.tryGet { int(basePath) }
}

else -> loadList(listSize, basePath) { path ->
load(listElementType, path, loaders)
}
}
}

private inline fun loadList(
listSize: Int,
basePath: ConfigPath,
getter: (ConfigPath) -> Any?
): List<Any> = MutableList(listSize) {
basePath.addLast(IntToken(it))
val got = getter(basePath)
basePath.removeLast()
return@MutableList got ?: error("List element not found")
}

inline fun <T> List<Provider>.tryGet(block: Provider.() -> T): T? {
for (loader in this) {
val res = block.invoke(loader)
if (res != null) return res
}
return null
}





data class Cfg(
val cfgA: Int,
val cfgB: String,
val cfgC: C,
val cfgD: Int? = null,
val cfgE: Int?,
val cfgF: Int = 1,
)

data class C(
val a: Int,
val b: String,
val li: List<Int>,
val ls: List<String>,
val lo: List<D>,
)

data class D(
val v: Int,
val w: String,
val cfg: Cfg,
)
157 changes: 0 additions & 157 deletions common/src/main/kotlin/com/daylifecraft/common/config/ConfigFile.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.daylifecraft.common.config

import java.util.LinkedList

@JvmInline
value class ConfigPath(val tokens: LinkedList<PathToken> = LinkedList<PathToken>()) {

val size
get() = tokens.size

fun first() = tokens.first()
fun last() = tokens.last()

fun addFirst(token: PathToken) = tokens.addFirst(token)
fun addLast(token: PathToken) = tokens.addLast(token)

fun removeFirst(): PathToken = tokens.removeFirst()
fun removeLast(): PathToken = tokens.removeLast()

override fun toString(): String {
return tokens.joinToString(".") {
when (it) {
is StringToken -> it.value
is IntToken -> "[${it.value}]"
}
}
}
}

sealed interface PathToken

@JvmInline
value class StringToken(val value: String) : PathToken

@JvmInline
value class IntToken(val value: Int) : PathToken
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.daylifecraft.common.config.providers

import com.daylifecraft.common.config.ConfigPath
import com.daylifecraft.common.config.IntToken
import com.daylifecraft.common.config.StringToken
import java.util.Locale

class EnvProvider(
private val prefix: String = "",
): Provider {

override fun int(configPath: ConfigPath): Int? {
return string(configPath)?.toInt()
}

override fun long(configPath: ConfigPath): Long? {
return string(configPath)?.toLong()
}

override fun float(configPath: ConfigPath): Float? {
return string(configPath)?.toFloat()
}

override fun double(configPath: ConfigPath): Double? {
return string(configPath)?.toDouble()
}

override fun boolean(configPath: ConfigPath): Boolean? {
return System.getenv(configPath.toEnv())?.toBoolean()
}

override fun string(configPath: ConfigPath): String? {
return System.getenv(configPath.toEnv())
}

override fun listSize(configPath: ConfigPath): Int? {
return int(configPath)
}

private fun ConfigPath.toEnv(): String = prefix + tokens.joinToString("_") {
when (it) {
is StringToken -> it.value
is IntToken -> "[${it.value}]"
}
}
.uppercase(Locale.getDefault())
}
Loading

0 comments on commit 436e009

Please sign in to comment.