korlibs-archive / korio

Korio: Kotlin cORoutines I/O : Virtual File System + Async/Sync Streams + Async TCP Client/Server + WebSockets for Multiplatform Kotlin 1.3
https://korlibs.soywiz.com/korio/
MIT License
361 stars 34 forks source link

Improve return type of `Yaml.decode`. #123

Closed Kesanov closed 3 years ago

Kesanov commented 3 years ago

Yaml.decode returns Any? at the moment. However, the set of values is much more narrow.

There are two improvements that come to mind:

  1. Use a sealed class that contains Map, List, Int, String, Bool, ...
  2. Return a YamlValue that makes indexing into the yaml value nicer:
    
    fun Yaml.deserialize(str: String) = YamlVal(decode(str))

class YamlVal(private val yaml: Any?) { val bool get() = yaml as? Boolean val str get() = yaml as? String val int get() = yaml as? Int val map get() = yaml as? Map<String, > val list get() = yaml as? List<> val keys get() = map?.keys val size get() = list?.size ?: map?.size operator fun get(key: Int ) = YamlVal(list?.get(key)) operator fun get(key: String) = YamlVal(map ?.get(key)) override fun toString() = yaml.toString() }


This allows nested indexing like: `street["houses"][246]["owner"]["name"].str`

`YamlValue` could in fact be the sealed class from `1`.
soywiz commented 3 years ago

YamlVal could be an inline class instead, right? That could reduce allocating extra objects.

I believe there is a Dyn class already here: https://github.com/korlibs/korio/blob/16aee3d0626f8a77cfee1d36b5edc713c45b9a53/korio/src/commonMain/kotlin/com/soywiz/korio/dynamic/Dyn.kt

That class would allow you to:

val street = Yaml.deserialize(myYmlString).dyn // notice the .dyn
val houseOwnerName = street["houses"][246]["owner"]["name"].str

Would that work for you? Or do you think it makes sense the YamlVal class?

Kesanov commented 3 years ago

The Dyn class looks to be what I was looking for. Thanks!