codecs.extended.ClosedRangeJSONCodec.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
object ClosedRangeJSONCodec : AbstractJSONCodec, JSONCodingContext>() {
override fun JSONDecoder.decode(valueType: JSONCodingType>): ClosedRange<*> {
@Suppress("UNCHECKED_CAST")
val elementType = valueType.arguments.single() as JSONCodingType>
return when (elementType.rawClass) {
Char::class -> decodeCharRange()
Comparable::class -> decodeComparableRange()
Double::class -> decodeDoubleRange()
Float::class -> decodeFloatRange()
Int::class -> decodeIntRange()
Long::class -> decodeLongRange()
else -> decodeOtherRange(elementType = elementType)
}
}
@Suppress("UNCHECKED_CAST")
private fun JSONDecoder.decodeComparableRange(): ClosedRange<*> {
var endInclusive: Comparable? = null
var start: Comparable? = null
readFromMapByElementValue { key ->
when (key) {
Fields.endInclusive -> endInclusive = readValue() as? Comparable
?: invalidPropertyError(key, details = "expected a comparable value")
Fields.start -> start = readValue() as? Comparable
?: invalidPropertyError(key, details = "expected a comparable value")
else -> skipValue()
}
}
return (start ?: missingPropertyError(Fields.start)) .. (endInclusive ?: missingPropertyError(Fields.endInclusive))
}
private fun JSONDecoder.decodeCharRange() =
CharRangeJSONCodec.run { decode(valueType = CharRangeJSONCodec.decodableType) }
private fun JSONDecoder.decodeDoubleRange(): ClosedFloatingPointRange {
var endInclusive = 0.0
var endInclusiveProvided = false
var start = 0.0
var startProvided = false
readFromMapByElementValue { key ->
when (key) {
Fields.endInclusive -> {
endInclusive = readDouble()
endInclusiveProvided = true
}
Fields.start -> {
start = readDouble()
startProvided = true
}
else -> skipValue()
}
}
if (!startProvided) missingPropertyError(Fields.start)
if (!endInclusiveProvided) missingPropertyError(Fields.endInclusive)
return start .. endInclusive
}
private fun JSONDecoder.decodeFloatRange(): ClosedFloatingPointRange {
var endInclusive = 0.0f
var endInclusiveProvided = false
var start = 0.0f
var startProvided = false
readFromMapByElementValue { key ->
when (key) {
Fields.endInclusive -> {
endInclusive = readFloat()
endInclusiveProvided = true
}
Fields.start -> {
start = readFloat()
startProvided = true
}
else -> skipValue()
}
}
if (!startProvided) missingPropertyError(Fields.start)
if (!endInclusiveProvided) missingPropertyError(Fields.endInclusive)
return start .. endInclusive
}
private fun JSONDecoder.decodeIntRange() =
IntRangeJSONCodec.run { decode(valueType = IntRangeJSONCodec.decodableType) }
private fun JSONDecoder.decodeLongRange() =
LongRangeJSONCodec.run { decode(valueType = LongRangeJSONCodec.decodableType) }
private fun JSONDecoder.decodeOtherRange(elementType: JSONCodingType>): ClosedRange<*> {
var endInclusive: Comparable? = null
var start: Comparable? = null
readFromMapByElementValue { key ->
when (key) {
Fields.endInclusive -> endInclusive = readValueOfType(elementType)
Fields.start -> start = readValueOfType(elementType)
else -> skipValue()
}
}
return (start ?: missingPropertyError(Fields.start)) .. (endInclusive ?: missingPropertyError(Fields.endInclusive))
}
override fun JSONEncoder.encode(value: ClosedRange<*>) {
writeIntoMap {
writeMapElement(Fields.start, value = value.start)
writeMapElement(Fields.endInclusive, value = value.endInclusive)
}
}
private object Fields {
const val endInclusive = "endInclusive"
const val start = "start"
}
}