Skip to content

Commit

Permalink
Add support for encoding Duration in HOCON format (Kotlin#2080)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexmihailov authored and fred01 committed Nov 24, 2022
1 parent fc454e0 commit 4d0c22f
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 126 deletions.
12 changes: 10 additions & 2 deletions formats/hocon/src/main/kotlin/kotlinx/serialization/hocon/Hocon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ import kotlinx.serialization.modules.*
* [Config] object represents "Human-Optimized Config Object Notation" —
* [HOCON][https://github.com/lightbend/config#using-hocon-the-json-superset].
*
* [Duration] objects are decoded using "HOCON duration format" -
* [Duration] objects are encoded/decoded using "HOCON duration format" -
* [Duration format][https://github.com/lightbend/config/blob/main/HOCON.md#duration-format]
* [Duration] objects encoding does not currently support duration HOCON format and uses standard Duration serializer which produces ISO-8601-2 string.
* [Duration] objects encoded using time unit short names: d, h, m, s, ms, us, ns.
* Encoding use the largest time unit.
* Example:
* 120.seconds -> 2 m
* 121.seconds -> 121 s
* 120.minutes -> 2 h
* 122.minutes -> 122 m
* 24.hours -> 1 d
* All restrictions on the maximum and minimum duration are specified in [Duration].
*
* @param [useConfigNamingConvention] switches naming resolution to config naming convention (hyphen separated).
* @param serializersModule A [SerializersModule] which should contain registered serializers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
package kotlinx.serialization.hocon

import com.typesafe.config.*
import kotlin.time.*
import kotlinx.serialization.*
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import kotlinx.serialization.internal.*
Expand Down Expand Up @@ -42,17 +44,18 @@ internal abstract class AbstractHoconEncoder(
override fun shouldEncodeElementDefault(descriptor: SerialDescriptor, index: Int): Boolean = hocon.encodeDefaults

override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
if (serializer !is AbstractPolymorphicSerializer<*> || hocon.useArrayPolymorphism) {
serializer.serialize(this, value)
return
when {
serializer.descriptor == Duration.serializer().descriptor -> encodeDuration(value as Duration)
serializer !is AbstractPolymorphicSerializer<*> || hocon.useArrayPolymorphism -> serializer.serialize(this, value)
else -> {
@Suppress("UNCHECKED_CAST")
val casted = serializer as AbstractPolymorphicSerializer<Any>
val actualSerializer = casted.findPolymorphicSerializer(this, value as Any)
writeDiscriminator = true

actualSerializer.serialize(this, value)
}
}

@Suppress("UNCHECKED_CAST")
val casted = serializer as AbstractPolymorphicSerializer<Any>
val actualSerializer = casted.findPolymorphicSerializer(this, value as Any)
writeDiscriminator = true

actualSerializer.serialize(this, value)
}

override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
Expand All @@ -79,6 +82,32 @@ internal abstract class AbstractHoconEncoder(
}

private fun configValueOf(value: Any?) = ConfigValueFactory.fromAnyRef(value)

private fun encodeDuration(value: Duration) {
val result = value.toComponents { seconds, nanoseconds ->
when {
nanoseconds == 0 -> {
if (seconds % 60 == 0L) { // minutes
if (seconds % 3600 == 0L) { // hours
if (seconds % 86400 == 0L) { // days
"${seconds / 86400} d"
} else {
"${seconds / 3600} h"
}
} else {
"${seconds / 60} m"
}
} else {
"$seconds s"
}
}
nanoseconds % 1_000_000 == 0 -> "${seconds * 1_000 + nanoseconds / 1_000_000} ms"
nanoseconds % 1_000 == 0 -> "${seconds * 1_000_000 + nanoseconds / 1_000} us"
else -> "${value.inWholeNanoseconds} ns"
}
}
encodeString(result)
}
}

@ExperimentalSerializationApi
Expand Down

This file was deleted.

Loading

0 comments on commit 4d0c22f

Please sign in to comment.