codecs.extended.EnumJSONCodec.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fluid-json-coding Show documentation
Show all versions of fluid-json-coding Show documentation
A JSON library written in pure Kotlin (coding extension)
package com.github.fluidsonic.fluid.json
import kotlin.reflect.*
sealed class EnumJSONCodec>(enumClass: KClass) : AbstractJSONCodec(
decodableType = jsonCodingType(enumClass)
) {
internal class OrdinalBased>(
enumClass: KClass
) : EnumJSONCodec(enumClass = enumClass) {
override fun JSONDecoder.decode(valueType: JSONCodingType): Value {
@Suppress("UNCHECKED_CAST")
val values = valueType.rawClass.java.enumConstants as Array
return readInt().let { ordinal ->
values.getOrElse(ordinal) {
invalidValueError("expected an integer between 0 and ${values.size - 1}")
}
}
}
override fun JSONEncoder.encode(value: Value) {
writeInt(value.ordinal)
}
}
internal class StringBased>(
enumClass: KClass,
strings: List
) : EnumJSONCodec(enumClass = enumClass) {
private val values: Array>
init {
values = enumClass.java.enumConstants
.mapIndexed { index, value ->
val string = strings[index]
value to string
}
.toTypedArray()
}
override fun JSONDecoder.decode(valueType: JSONCodingType) =
readString().let { name ->
values.firstOrNull { it.second == name }?.first
?: invalidValueError("expected one of: ${values.joinToString { "\"${it.second}\"" }}")
}
override fun JSONEncoder.encode(value: Value) {
writeString(values.first { it.first === value }.second)
}
}
}
@Suppress("FunctionName")
inline fun > EnumJSONCodec(
transformation: EnumJSONTransformation
) =
EnumJSONCodec(
enumClass = Value::class,
transformation = transformation
)
@Suppress("FunctionName")
fun > EnumJSONCodec(
enumClass: KClass,
transformation: EnumJSONTransformation
): EnumJSONCodec =
when (transformation) {
is EnumJSONTransformation.Name ->
EnumJSONCodec.StringBased(
enumClass = enumClass,
strings = enumClass.java.enumConstants.map { transformation.case.convert(it.name) }
)
is EnumJSONTransformation.Ordinal ->
EnumJSONCodec.OrdinalBased(enumClass = enumClass)
is EnumJSONTransformation.ToString ->
EnumJSONCodec.StringBased(
enumClass = enumClass,
strings = enumClass.java.enumConstants.map { transformation.case.convert(it.toString()) }
)
}