All Downloads are FREE. Search and download functionalities are using the official Maven repository.

codecs.extended.EnumJSONCodec.kt Maven / Gradle / Ivy

There is a newer version: 0.9.24
Show newest version
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()) }
			)
	}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy