KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/InternedJsonElementAdapter.kt

90 lines
2.7 KiB
Kotlin

package ru.dbotthepony.kstarbound.io.json
import com.google.common.collect.Interner
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import com.google.gson.TypeAdapter
import com.google.gson.internal.LazilyParsedNumber
import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
class InternedJsonElementAdapter(val stringInterner: Interner<String>) : TypeAdapter<JsonElement>() {
override fun write(out: JsonWriter, value: JsonElement?) {
return TypeAdapters.JSON_ELEMENT.write(out, value)
}
override fun read(`in`: JsonReader): JsonElement? {
return when (val p = `in`.peek()) {
JsonToken.STRING -> JsonPrimitive(stringInterner.intern(`in`.nextString()))
JsonToken.NUMBER -> JsonPrimitive(LazilyParsedNumber(`in`.nextString()))
JsonToken.BOOLEAN -> if (`in`.nextBoolean()) TRUE else FALSE
JsonToken.NULL -> JsonNull.INSTANCE
JsonToken.BEGIN_ARRAY -> arrays.read(`in`)
JsonToken.BEGIN_OBJECT -> objects.read(`in`)
else -> throw IllegalArgumentException(p.toString())
}
}
val objects = object : TypeAdapter<JsonObject>() {
override fun write(out: JsonWriter, value: JsonObject?) {
return TypeAdapters.JSON_ELEMENT.write(out, value)
}
override fun read(`in`: JsonReader): JsonObject? {
if (`in`.peek() == JsonToken.NULL)
return null
val output = JsonObject()
`in`.beginObject()
while (`in`.hasNext()) { output.add(stringInterner.intern(`in`.nextName()), this@InternedJsonElementAdapter.read(`in`)) }
`in`.endObject()
return output
}
}
val arrays = object : TypeAdapter<JsonArray>() {
override fun write(out: JsonWriter, value: JsonArray?) {
return TypeAdapters.JSON_ELEMENT.write(out, value)
}
override fun read(`in`: JsonReader): JsonArray? {
if (`in`.peek() == JsonToken.NULL)
return null
val output = JsonArray()
`in`.beginArray()
while (`in`.hasNext()) { output.add(this@InternedJsonElementAdapter.read(`in`)) }
`in`.endArray()
return output
}
}
companion object {
val TRUE = JsonPrimitive(true)
val FALSE = JsonPrimitive(false)
fun of(value: Boolean) = if (value) TRUE else FALSE
}
}
class InternedStringAdapter(val stringInterner: Interner<String>) : TypeAdapter<String>() {
override fun write(out: JsonWriter, value: String?) {
out.value(value)
}
override fun read(`in`: JsonReader): String? {
if (`in`.peek() == JsonToken.NULL)
return null
if (`in`.peek() == JsonToken.BOOLEAN)
return `in`.nextBoolean().toString()
return stringInterner.intern(`in`.nextString())
}
}