@@ -47,18 +47,28 @@ public sealed class Hocon(
4747 override val serializersModule: SerializersModule
4848 get() = this @Hocon.serializersModule
4949
50- abstract fun getTaggedConfigValue (tag : T ): ConfigValue
51-
52- private inline fun <reified E : Any > validateAndCast (tag : T , wrappedType : ConfigValueType ): E {
53- val cfValue = getTaggedConfigValue(tag)
54- if (cfValue.valueType() != wrappedType) throw SerializationException (" ${cfValue.origin().description()} required to be a $wrappedType " )
55- return cfValue.unwrapped() as E
50+ abstract fun <E > getValueFromTaggedConfig (tag : T , valueResolver : (Config , String ) -> E ): E
51+
52+ private inline fun <reified E : Any > validateAndCast (tag : T ): E {
53+ return try {
54+ when (E ::class ) {
55+ Number ::class -> getValueFromTaggedConfig(tag) { config, path -> config.getNumber(path) } as E
56+ Boolean ::class -> getValueFromTaggedConfig(tag) { config, path -> config.getBoolean(path) } as E
57+ String ::class -> getValueFromTaggedConfig(tag) { config, path -> config.getString(path) } as E
58+ else -> getValueFromTaggedConfig(tag) { config, path -> config.getAnyRef(path) } as E
59+ }
60+ } catch (e: ConfigException ) {
61+ val configOrigin = e.origin()
62+ val requiredType = E ::class .simpleName
63+ throw SerializationException (" ${configOrigin.description()} required to be of type $requiredType " )
64+ }
5665 }
5766
58- private fun getTaggedNumber (tag : T ) = validateAndCast<Number >(tag, ConfigValueType . NUMBER )
67+ private fun getTaggedNumber (tag : T ) = validateAndCast<Number >(tag)
5968
60- override fun decodeTaggedString (tag : T ) = validateAndCast<String >(tag, ConfigValueType . STRING )
69+ override fun decodeTaggedString (tag : T ) = validateAndCast<String >(tag)
6170
71+ override fun decodeTaggedBoolean (tag : T ) = validateAndCast<Boolean >(tag)
6272 override fun decodeTaggedByte (tag : T ): Byte = getTaggedNumber(tag).toByte()
6373 override fun decodeTaggedShort (tag : T ): Short = getTaggedNumber(tag).toShort()
6474 override fun decodeTaggedInt (tag : T ): Int = getTaggedNumber(tag).toInt()
@@ -67,17 +77,17 @@ public sealed class Hocon(
6777 override fun decodeTaggedDouble (tag : T ): Double = getTaggedNumber(tag).toDouble()
6878
6979 override fun decodeTaggedChar (tag : T ): Char {
70- val s = validateAndCast<String >(tag, ConfigValueType . STRING )
80+ val s = validateAndCast<String >(tag)
7181 if (s.length != 1 ) throw SerializationException (" String \" $s \" is not convertible to Char" )
7282 return s[0 ]
7383 }
7484
75- override fun decodeTaggedValue (tag : T ): Any = getTaggedConfigValue (tag).unwrapped()
85+ override fun decodeTaggedValue (tag : T ): Any = getValueFromTaggedConfig (tag) { c, s -> c.getAnyRef(s) }
7686
77- override fun decodeTaggedNotNullMark (tag : T ) = getTaggedConfigValue (tag).valueType() != ConfigValueType . NULL
87+ override fun decodeTaggedNotNullMark (tag : T ) = getValueFromTaggedConfig (tag) { c, s -> ! c.getIsNull(s) }
7888
7989 override fun decodeTaggedEnum (tag : T , enumDescriptor : SerialDescriptor ): Int {
80- val s = validateAndCast<String >(tag, ConfigValueType . STRING )
90+ val s = validateAndCast<String >(tag)
8191 return enumDescriptor.getElementIndexOrThrow(s)
8292 }
8393 }
@@ -107,14 +117,6 @@ public sealed class Hocon(
107117 else originalName.replace(NAMING_CONVENTION_REGEX ) { " -${it.value.lowercase()} " }
108118 }
109119
110- override fun getTaggedConfigValue (tag : String ): ConfigValue {
111- return conf.getValue(tag)
112- }
113-
114- override fun decodeTaggedNotNullMark (tag : String ): Boolean {
115- return ! conf.getIsNull(tag)
116- }
117-
118120 override fun decodeNotNullMark (): Boolean {
119121 // Tag might be null for top-level deserialization
120122 val currentTag = currentTagOrNull ? : return ! conf.isEmpty
@@ -159,6 +161,10 @@ public sealed class Hocon(
159161 else -> this
160162 }
161163 }
164+
165+ override fun <E > getValueFromTaggedConfig (tag : String , valueResolver : (Config , String ) -> E ): E {
166+ return valueResolver(conf, tag)
167+ }
162168 }
163169
164170 private inner class ListConfigReader (private val list : ConfigList ) : ConfigConverter<Int>() {
@@ -179,7 +185,11 @@ public sealed class Hocon(
179185 return if (ind > list.size - 1 ) DECODE_DONE else ind
180186 }
181187
182- override fun getTaggedConfigValue (tag : Int ): ConfigValue = list[tag]
188+ override fun <E > getValueFromTaggedConfig (tag : Int , valueResolver : (Config , String ) -> E ): E {
189+ val tagString = tag.toString()
190+ val configValue = valueResolver(list[tag].atKey(tagString), tagString)
191+ return configValue
192+ }
183193 }
184194
185195 private inner class MapConfigReader (map : ConfigObject ) : ConfigConverter<Int>() {
@@ -210,13 +220,16 @@ public sealed class Hocon(
210220 return if (ind >= indexSize) DECODE_DONE else ind
211221 }
212222
213- override fun getTaggedConfigValue (tag : Int ): ConfigValue {
223+ override fun < E > getValueFromTaggedConfig (tag : Int , valueResolver : ( Config , String ) -> E ): E {
214224 val idx = tag / 2
215- return if (tag % 2 == 0 ) { // entry as string
216- ConfigValueFactory .fromAnyRef(keys[idx])
225+ val tagString = tag.toString()
226+ val configValue = if (tag % 2 == 0 ) { // entry as string
227+ ConfigValueFactory .fromAnyRef(keys[idx]).atKey(tagString)
217228 } else {
218- values[idx]
229+ val configValue = values[idx]
230+ configValue.atKey(tagString)
219231 }
232+ return valueResolver(configValue, tagString)
220233 }
221234 }
222235
0 commit comments