@@ -90,16 +90,16 @@ internal class SettingsEncoder(
90
90
}
91
91
92
92
@ExperimentalSerializationApi
93
- internal class SettingsDecoder (
94
- private val settings : Settings ,
93
+ internal abstract class AbstractSettingsDecoder (
94
+ protected val settings : Settings ,
95
95
private val key : String ,
96
96
public override val serializersModule : SerializersModule
97
97
) : AbstractDecoder() {
98
98
99
99
// Stacks of keys and indices so we can track index at arbitrary levels to know what we're decoding next
100
100
private val keyStack = ArrayDeque <String >().apply { add(key) }
101
101
private val indexStack = ArrayDeque <Int >().apply { add(0 ) }
102
- private fun getKey (): String = keyStack.joinToString(" ." )
102
+ protected fun getKey (): String = keyStack.joinToString(" ." )
103
103
104
104
// Depth increases with beginStructure() and decreases with endStructure(). Subtly different from stack sizes.
105
105
// This is important so we can tell whether the last items on the stack refer to the current parent or a sibling.
@@ -161,6 +161,27 @@ internal class SettingsDecoder(
161
161
}
162
162
}
163
163
164
+ // Hook to reset state after we throw during deserializationError()
165
+ internal fun reset () {
166
+ keyStack.clear()
167
+ indexStack.clear()
168
+ depth = 0
169
+ keyStack.add(key)
170
+ indexStack.add(0 )
171
+ }
172
+ }
173
+
174
+ @ExperimentalSerializationApi
175
+ internal class SettingsDecoder (
176
+ settings : Settings ,
177
+ key : String ,
178
+ serializersModule : SerializersModule
179
+ ) : AbstractSettingsDecoder(
180
+ settings,
181
+ key,
182
+ serializersModule
183
+ ) {
184
+
164
185
public override fun decodeCollectionSize (descriptor : SerialDescriptor ): Int =
165
186
settings.getIntOrNull(" ${getKey()} .size" ) ? : deserializationError()
166
187
@@ -183,100 +204,26 @@ internal class SettingsDecoder(
183
204
public override fun decodeLong (): Long = settings.getLongOrNull(getKey()) ? : deserializationError()
184
205
public override fun decodeShort (): Short = settings.getIntOrNull(getKey())?.toShort() ? : deserializationError()
185
206
public override fun decodeString (): String = settings.getStringOrNull(getKey()) ? : deserializationError()
186
-
187
- // Hook to reset state after we throw during deserializationError()
188
- internal fun reset () {
189
- keyStack.clear()
190
- indexStack.clear()
191
- depth = 0
192
- keyStack.add(key)
193
- indexStack.add(0 )
194
- }
195
207
}
196
208
197
209
// (Ab)uses Decoder machinery to enumerate all keys related to a serialized value, so they can be removed
198
210
@ExperimentalSerializationApi
199
211
internal class SettingsRemover (
200
- private val settings : Settings ,
201
- private val key : String ,
202
- public override val serializersModule : SerializersModule
203
- ) : AbstractDecoder() {
204
-
212
+ settings : Settings ,
213
+ key : String ,
214
+ serializersModule : SerializersModule
215
+ ) : AbstractSettingsDecoder(
216
+ settings,
217
+ key,
218
+ serializersModule
219
+ ) {
205
220
private val keys = mutableListOf<String >()
206
221
fun removeKeys () {
207
222
for (key in keys) {
208
223
settings.remove(key)
209
224
}
210
225
}
211
226
212
- // Stacks of keys and indices so we can track index at arbitrary levels to know what we're decoding next
213
- private val keyStack = ArrayDeque <String >().apply { add(key) }
214
- private val indexStack = ArrayDeque <Int >().apply { add(0 ) }
215
- private fun getKey (): String = keyStack.joinToString(" ." )
216
-
217
- // Depth increases with beginStructure() and decreases with endStructure(). Subtly different from stack sizes.
218
- // This is important so we can tell whether the last items on the stack refer to the current parent or a sibling.
219
- private var depth = 0
220
-
221
-
222
- public override fun decodeElementIndex (descriptor : SerialDescriptor ): Int {
223
- if (keyStack.size > depth) {
224
- keyStack.removeLast()
225
- indexStack.removeLast()
226
- }
227
-
228
- // Can usually ask descriptor for a size, except for collections
229
- val size = when (descriptor.kind) {
230
- StructureKind .LIST -> decodeCollectionSize(descriptor)
231
- StructureKind .MAP -> 2 * decodeCollectionSize(descriptor) // Maps look like lists [k1, v1, k2, v2, ...]
232
- else -> descriptor.elementsCount
233
- }
234
-
235
- return getNextIndex(descriptor, size)
236
- }
237
-
238
- private tailrec fun getNextIndex (descriptor : SerialDescriptor , size : Int ): Int {
239
- val index = indexStack.removeLast()
240
- indexStack.addLast(index + 1 )
241
-
242
- return when {
243
- index >= size -> CompositeDecoder .DECODE_DONE
244
- isMissingAndOptional(descriptor, index) -> getNextIndex(descriptor, size)
245
- else -> {
246
- keyStack.add(descriptor.getElementName(index))
247
- indexStack.add(0 )
248
- index
249
- }
250
- }
251
- }
252
-
253
- private fun isMissingAndOptional (descriptor : SerialDescriptor , index : Int ): Boolean {
254
- val key = " ${getKey()} .${descriptor.getElementName(index)} "
255
- // Descriptor shows key is optional, key is not present, and nullability doesn't indicate key should be present
256
- val output = descriptor.isElementOptional(index) && descriptor.isNullable &&
257
- key !in settings && settings.getBooleanOrNull(" $key ?" ) != true
258
- keys.add(key)
259
- keys.add(" $key ?" )
260
- return output
261
- }
262
-
263
-
264
- public override fun beginStructure (descriptor : SerialDescriptor ): CompositeDecoder {
265
- depth++
266
- return super .beginStructure(descriptor)
267
- }
268
-
269
- public override fun endStructure (descriptor : SerialDescriptor ) {
270
- depth--
271
- keyStack.removeLast()
272
- indexStack.removeLast()
273
- if (keyStack.isEmpty()) {
274
- // We've reached the end of everything, so reset for potential decoder reuse
275
- keyStack.add(key)
276
- indexStack.add(0 )
277
- }
278
- }
279
-
280
227
public override fun decodeCollectionSize (descriptor : SerialDescriptor ): Int {
281
228
val output = settings.getInt(" ${getKey()} .size" , 0 )
282
229
keys.add(" ${getKey()} .size" )
0 commit comments