Более функциональный подход к typeadapter
This commit is contained in:
parent
53c4c3fa11
commit
366e59cf14
@ -33,7 +33,7 @@ data class MaterialModifier(
|
||||
.auto(MaterialModifier::grass)
|
||||
.list(MaterialModifier::miningSounds)
|
||||
.auto(MaterialModifier::miningParticle)
|
||||
.plain(MaterialModifier::renderTemplate, RenderTemplate.CACHE)
|
||||
.add(MaterialModifier::renderTemplate, RenderTemplate.CACHE)
|
||||
.auto(MaterialModifier::renderParameters)
|
||||
.build()
|
||||
|
||||
|
@ -38,7 +38,7 @@ data class TileDefinition(
|
||||
TileDefinition::health,
|
||||
TileDefinition::category
|
||||
)
|
||||
.plain(TileDefinition::renderTemplate, RenderTemplate.CACHE)
|
||||
.add(TileDefinition::renderTemplate, RenderTemplate.CACHE)
|
||||
.auto(
|
||||
TileDefinition::renderParameters,
|
||||
)
|
||||
|
41
src/main/kotlin/ru/dbotthepony/kstarbound/io/json/Ext.kt
Normal file
41
src/main/kotlin/ru/dbotthepony/kstarbound/io/json/Ext.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package ru.dbotthepony.kstarbound.io.json
|
||||
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonWriter
|
||||
|
||||
fun <T> TypeAdapter<T>.transformRead(transformer: (T) -> T): TypeAdapter<T> {
|
||||
return object : TypeAdapter<T>() {
|
||||
override fun write(out: JsonWriter, value: T) {
|
||||
return this@transformRead.write(out, value)
|
||||
}
|
||||
|
||||
override fun read(`in`: JsonReader): T {
|
||||
return transformer(this@transformRead.read(`in`))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> TypeAdapter<T>.transformWrite(transformer: (T) -> T): TypeAdapter<T> {
|
||||
return object : TypeAdapter<T>() {
|
||||
override fun write(out: JsonWriter, value: T) {
|
||||
return this@transformWrite.write(out, transformer(value))
|
||||
}
|
||||
|
||||
override fun read(`in`: JsonReader): T {
|
||||
return this@transformWrite.read(`in`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> TypeAdapter<T>.transform(transformRead: (T) -> T, transformWrite: (T) -> T): TypeAdapter<T> {
|
||||
return object : TypeAdapter<T>() {
|
||||
override fun write(out: JsonWriter, value: T) {
|
||||
return this@transform.write(out, transformWrite(value))
|
||||
}
|
||||
|
||||
override fun read(`in`: JsonReader): T {
|
||||
return transformRead(this@transform.read(`in`))
|
||||
}
|
||||
}
|
||||
}
|
@ -377,7 +377,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
/**
|
||||
* Добавляет поле с определённым адаптером
|
||||
*/
|
||||
fun <V> plain(field: KProperty1<T, V>, adapter: TypeAdapter<V>): Builder<T> {
|
||||
fun <V> add(field: KProperty1<T, V>, adapter: TypeAdapter<V>): Builder<T> {
|
||||
types.add(PackedProperty(field, adapter))
|
||||
return this
|
||||
}
|
||||
@ -410,7 +410,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Список неизменяем (создаётся объект [ImmutableList])
|
||||
*/
|
||||
fun <V : Any> list(field: KProperty1<T, List<V>?>, type: Class<V>, transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
||||
types.add(PackedProperty(field, ListAdapter(type), transformer = transformer))
|
||||
types.add(PackedProperty(field, ListAdapter(type).nullSafe(), transformer = transformer))
|
||||
return this
|
||||
}
|
||||
|
||||
@ -420,7 +420,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Список неизменяем (создаётся объект [ImmutableList])
|
||||
*/
|
||||
inline fun <reified V : Any> list(field: KProperty1<T, List<V>?>, noinline transformer: (List<V>?) -> List<V>? = { it }): Builder<T> {
|
||||
return this.list(field, V::class.java, transformer)
|
||||
return add(field, ListAdapter(V::class.java).nullSafe())
|
||||
}
|
||||
|
||||
/**
|
||||
@ -453,7 +453,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||
*/
|
||||
fun <K : Any, V : Any> map(field: KProperty1<T, Map<K, V>?>, keyType: KClass<K>, valueType: KClass<V>): Builder<T> {
|
||||
types.add(PackedProperty(field, MapAdapter(keyType.java, valueType.java)))
|
||||
types.add(PackedProperty(field, MapAdapter(keyType.java, valueType.java).nullSafe()))
|
||||
return this
|
||||
}
|
||||
|
||||
@ -463,7 +463,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||
*/
|
||||
fun <V> map(field: KProperty1<T, Map<String, V>?>, valueType: Class<V>): Builder<T> {
|
||||
types.add(PackedProperty(field, StringMapAdapter(valueType)))
|
||||
types.add(PackedProperty(field, String2ObjectAdapter(valueType).nullSafe()))
|
||||
return this
|
||||
}
|
||||
|
||||
@ -473,7 +473,7 @@ class KConcreteTypeAdapter<T : Any> private constructor(
|
||||
* Таблица неизменяема (создаётся объект [ImmutableMap])
|
||||
*/
|
||||
fun <V : Any> map(field: KProperty1<T, Map<String, V>?>, valueType: KClass<V>): Builder<T> {
|
||||
types.add(PackedProperty(field, StringMapAdapter(valueType.java)))
|
||||
types.add(PackedProperty(field, String2ObjectAdapter(valueType.java).nullSafe()))
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -8,18 +8,18 @@ import com.google.gson.stream.JsonToken
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
|
||||
class ListAdapter<T>(private val type: Class<T>) : TypeAdapter<List<T>?>() {
|
||||
private val resolvedBound by lazy { Starbound.getTypeAdapter(type) }
|
||||
fun <T : Any> TypeAdapter<T>.asList(): TypeAdapter<List<T>> {
|
||||
return ListAdapter(this)
|
||||
}
|
||||
|
||||
override fun write(out: JsonWriter, value: List<T>?) {
|
||||
class ListAdapter<T : Any>(val elementAdapter: TypeAdapter<T>, val valueTransformer: (T) -> T = { it }) : TypeAdapter<List<T>>() {
|
||||
constructor(type: Class<T>) : this(LazyTypeProvider(type))
|
||||
|
||||
override fun write(out: JsonWriter, value: List<T>) {
|
||||
out.beginArray()
|
||||
|
||||
if (value != null) {
|
||||
val resolvedBound = resolvedBound
|
||||
|
||||
for (v in value) {
|
||||
resolvedBound.write(out, v)
|
||||
}
|
||||
for (v in value) {
|
||||
elementAdapter.write(out, v)
|
||||
}
|
||||
|
||||
out.endArray()
|
||||
@ -29,15 +29,14 @@ class ListAdapter<T>(private val type: Class<T>) : TypeAdapter<List<T>?>() {
|
||||
reader.beginArray()
|
||||
|
||||
val builder = ImmutableList.builder<T>()
|
||||
val resolvedBound = resolvedBound
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||
val readObject = resolvedBound.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
||||
builder.add(readObject as T)
|
||||
val readObject = elementAdapter.read(reader) ?: throw JsonSyntaxException("List does not accept nulls")
|
||||
builder.add(valueTransformer(readObject))
|
||||
}
|
||||
|
||||
reader.endArray()
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,23 +7,17 @@ import com.google.gson.stream.JsonToken
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
|
||||
class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Class<V>) : TypeAdapter<Map<K, V>?>() {
|
||||
private val resolvedKey by lazy { Starbound.getTypeAdapter(keyType) }
|
||||
private val resolvedValue by lazy { Starbound.getTypeAdapter(valueType) }
|
||||
class MapAdapter<K, V>(val keyAdapter: TypeAdapter<K>, val valueAdapter: TypeAdapter<V>) : TypeAdapter<Map<K, V>>() {
|
||||
constructor(keyType: Class<K>, valueType: Class<V>) : this(LazyTypeProvider(keyType), LazyTypeProvider(valueType))
|
||||
|
||||
override fun write(out: JsonWriter, value: Map<K, V>?) {
|
||||
override fun write(out: JsonWriter, value: Map<K, V>) {
|
||||
out.beginArray()
|
||||
|
||||
if (value != null) {
|
||||
val resolvedKey = resolvedKey
|
||||
val resolvedValue = resolvedValue
|
||||
|
||||
for ((k, v) in value) {
|
||||
out.beginArray()
|
||||
resolvedKey.write(out, k)
|
||||
resolvedValue.write(out, v)
|
||||
out.endArray()
|
||||
}
|
||||
for ((k, v) in value) {
|
||||
out.beginArray()
|
||||
keyAdapter.write(out, k)
|
||||
valueAdapter.write(out, v)
|
||||
out.endArray()
|
||||
}
|
||||
|
||||
out.endArray()
|
||||
@ -34,12 +28,9 @@ class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Cla
|
||||
|
||||
val builder = ImmutableMap.builder<K, V>()
|
||||
|
||||
val resolvedKey = resolvedKey
|
||||
val resolvedValue = resolvedValue
|
||||
|
||||
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||
reader.beginArray()
|
||||
builder.put(resolvedKey.read(reader), resolvedValue.read(reader))
|
||||
builder.put(keyAdapter.read(reader), valueAdapter.read(reader))
|
||||
reader.endArray()
|
||||
}
|
||||
|
||||
@ -47,4 +38,4 @@ class MapAdapter<K, V>(private val keyType: Class<K>, private val valueType: Cla
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package ru.dbotthepony.kstarbound.io.json
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonToken
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
|
||||
fun <T> TypeAdapter<T>.asJsonObject(): TypeAdapter<Map<String, T>> {
|
||||
return String2ObjectAdapter(this)
|
||||
}
|
||||
|
||||
class String2ObjectAdapter<T>(val adapter: TypeAdapter<T>) : TypeAdapter<Map<String, T>>() {
|
||||
constructor(type: Class<T>) : this(LazyTypeProvider(type))
|
||||
|
||||
override fun write(out: JsonWriter, value: Map<String, T>) {
|
||||
out.beginObject()
|
||||
|
||||
for ((k, v) in value) {
|
||||
out.name(k)
|
||||
adapter.write(out, v)
|
||||
}
|
||||
|
||||
out.endObject()
|
||||
}
|
||||
|
||||
override fun read(reader: JsonReader): Map<String, T> {
|
||||
val builder = ImmutableMap.builder<String, T>()
|
||||
|
||||
reader.beginObject()
|
||||
|
||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||
builder.put(Starbound.assetStringInterner.intern(reader.nextName()), adapter.read(reader))
|
||||
}
|
||||
|
||||
reader.endObject()
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package ru.dbotthepony.kstarbound.io.json
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.google.gson.TypeAdapter
|
||||
import com.google.gson.stream.JsonReader
|
||||
import com.google.gson.stream.JsonToken
|
||||
import com.google.gson.stream.JsonWriter
|
||||
import ru.dbotthepony.kstarbound.Starbound
|
||||
|
||||
class StringMapAdapter<V>(private val type: Class<V>) : TypeAdapter<Map<String, V>?>() {
|
||||
private val resolvedBound by lazy { Starbound.getTypeAdapter(type) }
|
||||
|
||||
override fun write(out: JsonWriter, value: Map<String, V>?) {
|
||||
val resolvedBound = resolvedBound
|
||||
|
||||
out.beginObject()
|
||||
|
||||
if (value != null) {
|
||||
for ((k, v) in value) {
|
||||
out.name(k)
|
||||
resolvedBound.write(out, v)
|
||||
}
|
||||
}
|
||||
|
||||
out.endObject()
|
||||
}
|
||||
|
||||
override fun read(reader: JsonReader): Map<String, V> {
|
||||
val builder = ImmutableMap.builder<String, V>()
|
||||
|
||||
reader.beginObject()
|
||||
|
||||
val resolvedBound = resolvedBound
|
||||
|
||||
while (reader.peek() != JsonToken.END_OBJECT) {
|
||||
builder.put(Starbound.assetStringInterner.intern(reader.nextName()), resolvedBound.read(reader))
|
||||
}
|
||||
|
||||
reader.endObject()
|
||||
|
||||
return builder.build()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user