Skip to content

Commit 331c666

Browse files
committed
Simplify element decoding logic and ensuring all element indexes are accounted for
1 parent 0db6607 commit 331c666

File tree

4 files changed

+16
-29
lines changed

4 files changed

+16
-29
lines changed

bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/BsonDecoder.kt

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ internal open class DefaultBsonDecoder(
6363
private data class ElementMetadata(val name: String, val nullable: Boolean, var processed: Boolean = false)
6464
private var elementsMetadata: Array<ElementMetadata>? = null
6565
private var currentIndex: Int = UNKNOWN_INDEX
66-
private var level = 0
6766

6867
companion object {
6968
val validKeyKinds = setOf(PrimitiveKind.STRING, PrimitiveKind.CHAR, SerialKind.ENUM)
@@ -85,35 +84,24 @@ internal open class DefaultBsonDecoder(
8584
override fun decodeElementIndex(descriptor: SerialDescriptor): Int {
8685
initElementMetadata(descriptor)
8786
currentIndex = decodeElementIndexImpl(descriptor)
87+
elementsMetadata?.getOrNull(currentIndex)?.processed = true
8888
return currentIndex
8989
}
9090

9191
@Suppress("ReturnCount", "ComplexMethod")
9292
private fun decodeElementIndexImpl(descriptor: SerialDescriptor): Int {
93+
val elementMetadata = elementsMetadata ?: error("elementsMetadata may not be null.")
9394
val name: String? =
9495
when (reader.state ?: error("State of reader may not be null.")) {
9596
AbstractBsonReader.State.NAME -> reader.readName()
9697
AbstractBsonReader.State.VALUE -> reader.currentName
9798
AbstractBsonReader.State.TYPE -> {
98-
val type = reader.readBsonType()
99-
if (type.isContainer) {
100-
level++
101-
}
99+
reader.readBsonType()
102100
return decodeElementIndexImpl(descriptor)
103101
}
104102
AbstractBsonReader.State.END_OF_DOCUMENT,
105-
AbstractBsonReader.State.END_OF_ARRAY -> {
106-
level--
107-
val elementMetadata = elementsMetadata ?: error("elementsMetadata may not be null.")
108-
109-
return if (level == 0) {
110-
DECODE_DONE
111-
} else {
112-
currentIndex = elementMetadata.indexOfFirst { it.nullable && !it.processed }
113-
if (currentIndex >= 0) elementMetadata[currentIndex].processed = true
114-
return currentIndex
115-
}
116-
}
103+
AbstractBsonReader.State.END_OF_ARRAY ->
104+
return elementMetadata.indexOfFirst { it.nullable && !it.processed }
117105
else -> null
118106
}
119107

@@ -194,7 +182,6 @@ internal open class DefaultBsonDecoder(
194182

195183
private inline fun <T> readOrThrow(action: () -> T, bsonType: BsonType): T {
196184
return try {
197-
elementsMetadata?.get(currentIndex)?.processed = true
198185
action()
199186
} catch (e: BsonInvalidOperationException) {
200187
throw BsonInvalidOperationException(

bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import org.bson.BsonDocumentWriter
2929
import org.bson.BsonInvalidOperationException
3030
import org.bson.BsonMaxKey
3131
import org.bson.BsonMinKey
32-
import org.bson.BsonNull
3332
import org.bson.BsonUndefined
3433
import org.bson.codecs.DecoderContext
3534
import org.bson.codecs.EncoderContext
@@ -119,7 +118,6 @@ class KotlinSerializerCodecTest {
119118
| "int64": {"${'$'}numberLong": "52"},
120119
| "maxKey": {"${'$'}maxKey": 1},
121120
| "minKey": {"${'$'}minKey": 1},
122-
| "null": null,
123121
| "objectId": {"${'$'}oid": "211111111111111111111112"},
124122
| "regex": {"${'$'}regularExpression": {"pattern": "^test.*regex.*xyz$", "options": "i"}},
125123
| "string": "the fox ...",
@@ -494,7 +492,6 @@ class KotlinSerializerCodecTest {
494492
allBsonTypesDocument["int64"]!!.asInt64(),
495493
allBsonTypesDocument["maxKey"]!! as BsonMaxKey,
496494
allBsonTypesDocument["minKey"]!! as BsonMinKey,
497-
allBsonTypesDocument["null"]!! as BsonNull,
498495
allBsonTypesDocument["objectId"]!!.asObjectId(),
499496
allBsonTypesDocument["regex"]!!.asRegularExpression(),
500497
allBsonTypesDocument["string"]!!.asString(),
@@ -507,7 +504,6 @@ class KotlinSerializerCodecTest {
507504

508505
@Test
509506
fun testDataClassOptionalBsonValues() {
510-
511507
val dataClass =
512508
DataClassOptionalBsonValues(
513509
allBsonTypesDocument["id"]!!.asObjectId().value,
@@ -529,7 +525,6 @@ class KotlinSerializerCodecTest {
529525
allBsonTypesDocument["int64"]!!.asInt64(),
530526
allBsonTypesDocument["maxKey"]!! as BsonMaxKey,
531527
allBsonTypesDocument["minKey"]!! as BsonMinKey,
532-
allBsonTypesDocument["null"]!! as BsonNull,
533528
allBsonTypesDocument["objectId"]!!.asObjectId(),
534529
allBsonTypesDocument["regex"]!!.asRegularExpression(),
535530
allBsonTypesDocument["string"]!!.asString(),
@@ -565,11 +560,18 @@ class KotlinSerializerCodecTest {
565560
null,
566561
null,
567562
null,
568-
null,
569-
null,
570-
)
563+
null)
571564

572565
assertRoundTrips("{}", emptyDataClass)
566+
assertRoundTrips(
567+
"""{ "id": null, "arrayEmpty": null, "arraySimple": null, "arrayComplex": null, "arrayMixedTypes": null,
568+
| "arrayComplexMixedTypes": null, "binary": null, "boolean": null, "code": null, "codeWithScope": null,
569+
| "dateTime": null, "decimal128": null, "documentEmpty": null, "document": null, "double": null,
570+
| "int32": null, "int64": null, "maxKey": null, "minKey": null, "objectId": null, "regex": null,
571+
| "string": null, "symbol": null, "timestamp": null, "undefined": null }"""
572+
.trimMargin(),
573+
emptyDataClass,
574+
BsonConfiguration(explicitNulls = true))
573575
}
574576

575577
@Test

bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/samples/DataClasses.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import org.bson.BsonJavaScript
3434
import org.bson.BsonJavaScriptWithScope
3535
import org.bson.BsonMaxKey
3636
import org.bson.BsonMinKey
37-
import org.bson.BsonNull
3837
import org.bson.BsonObjectId
3938
import org.bson.BsonRegularExpression
4039
import org.bson.BsonString
@@ -201,7 +200,6 @@ data class DataClassBsonValues(
201200
@Contextual val int64: BsonInt64,
202201
@Contextual val maxKey: BsonMaxKey,
203202
@Contextual val minKey: BsonMinKey,
204-
@Contextual val `null`: BsonNull,
205203
@Contextual val objectId: BsonObjectId,
206204
@Contextual val regex: BsonRegularExpression,
207205
@Contextual val string: BsonString,
@@ -231,7 +229,6 @@ data class DataClassOptionalBsonValues(
231229
@Contextual val int64: BsonInt64?,
232230
@Contextual val maxKey: BsonMaxKey?,
233231
@Contextual val minKey: BsonMinKey?,
234-
@Contextual val `null`: BsonNull?,
235232
@Contextual val objectId: BsonObjectId?,
236233
@Contextual val regex: BsonRegularExpression?,
237234
@Contextual val string: BsonString?,

config/detekt/baseline.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
<ID>LargeClass:MongoCollectionTest.kt$MongoCollectionTest</ID>
77
<ID>LongMethod:FindFlowTest.kt$FindFlowTest$@Suppress("DEPRECATION") @Test fun shouldCallTheUnderlyingMethods()</ID>
88
<ID>LongMethod:FindIterableTest.kt$FindIterableTest$@Suppress("DEPRECATION") @Test fun shouldCallTheUnderlyingMethods()</ID>
9+
<ID>LongMethod:KotlinSerializerCodecTest.kt$KotlinSerializerCodecTest$@Test fun testDataClassOptionalBsonValues()</ID>
910
<ID>MaxLineLength:MapReduceFlow.kt$MapReduceFlow$*</ID>
1011
<ID>MaxLineLength:MapReduceIterable.kt$MapReduceIterable$*</ID>
1112
<ID>SwallowedException:MockitoHelper.kt$MockitoHelper.DeepReflectionEqMatcher$e: Throwable</ID>

0 commit comments

Comments
 (0)