diff --git a/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformDecoder.kt b/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformDecoder.kt index d7793156..7ed1ad76 100644 --- a/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformDecoder.kt +++ b/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformDecoder.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, OpenSavvy and contributors. + * Copyright (c) 2025-2026, OpenSavvy and contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,8 +36,7 @@ import opensavvy.ktmongo.bson.multiplatform.BsonFactory import opensavvy.ktmongo.bson.multiplatform.Bytes import opensavvy.ktmongo.bson.multiplatform.impl.read.MultiplatformArrayReader import opensavvy.ktmongo.bson.multiplatform.impl.read.MultiplatformDocumentReader -import opensavvy.ktmongo.bson.types.ObjectId -import opensavvy.ktmongo.bson.types.Timestamp +import opensavvy.ktmongo.bson.types.* import opensavvy.ktmongo.dsl.LowLevelApi import kotlin.time.ExperimentalTime import kotlin.time.Instant @@ -148,6 +147,10 @@ internal class BsonDecoder( private val timestamp = Timestamp.Serializer.descriptor private val uuid = Uuid.serializer().descriptor private val instant = Instant.serializer().descriptor + private val vector = Vector.serializer().descriptor + private val floatVector = FloatVector.serializer().descriptor + private val booleanVector = BooleanVector.serializer().descriptor + private val byteVector = ByteVector.serializer().descriptor override fun decodeSerializableValue(deserializer: DeserializationStrategy): T { @Suppress("UNCHECKED_CAST") return when (deserializer.descriptor) { @@ -161,6 +164,7 @@ internal class BsonDecoder( Uuid.fromByteArray(source.readBinaryData()) as T } instant -> source.readInstant() as T + vector, floatVector, booleanVector, byteVector -> Vector.fromBinaryData(source.readBinaryData()) as T // General case: do what the serializer says else -> deserializer.deserialize(this) diff --git a/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformEncoder.kt b/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformEncoder.kt index d033184e..9e2a2654 100644 --- a/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformEncoder.kt +++ b/bson-multiplatform/src/commonMain/kotlin/serialization/MultiplatformEncoder.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, OpenSavvy and contributors. + * Copyright (c) 2025-2026, OpenSavvy and contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,7 @@ import opensavvy.ktmongo.bson.multiplatform.Bson import opensavvy.ktmongo.bson.multiplatform.BsonFactory import opensavvy.ktmongo.bson.multiplatform.impl.write.CompletableBsonFieldWriter import opensavvy.ktmongo.bson.multiplatform.impl.write.CompletableBsonValueWriter -import opensavvy.ktmongo.bson.types.ObjectId -import opensavvy.ktmongo.bson.types.Timestamp +import opensavvy.ktmongo.bson.types.* import opensavvy.ktmongo.dsl.DangerousMongoApi import opensavvy.ktmongo.dsl.LowLevelApi import kotlin.time.ExperimentalTime @@ -138,6 +137,10 @@ private class BsonEncoder(override val serializersModule: SerializersModule, val private val timestamp = Timestamp.Serializer.descriptor private val uuid = Uuid.serializer().descriptor private val instant = Instant.serializer().descriptor + private val vector = Vector.serializer().descriptor + private val floatVector = FloatVector.serializer().descriptor + private val booleanVector = BooleanVector.serializer().descriptor + private val byteVector = ByteVector.serializer().descriptor override fun encodeSerializableValue(serializer: SerializationStrategy, value: T) { when (serializer.descriptor) { // Special cases where we provide our own encoder @@ -146,6 +149,7 @@ private class BsonEncoder(override val serializersModule: SerializersModule, val timestamp -> out.writeTimestamp(value as Timestamp) uuid -> out.writeBinaryData(4u, (value as Uuid).toByteArray()) instant -> out.writeInstant(value as Instant) + vector, floatVector, booleanVector, byteVector -> out.writeBinaryData(0x09u, (value as Vector).toBinaryData()) // General case: do what the serializer says else -> serializer.serialize(this, value) diff --git a/bson-tests/src/commonMain/kotlin/raw/BinaryTest.kt b/bson-tests/src/commonMain/kotlin/raw/BinaryTest.kt index 1a64cc3e..b06676d9 100644 --- a/bson-tests/src/commonMain/kotlin/raw/BinaryTest.kt +++ b/bson-tests/src/commonMain/kotlin/raw/BinaryTest.kt @@ -254,6 +254,17 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { } ) + @Serializable + data class V( + val x: Vector, + ) + + @Serializable + data class VFloat( + val x: FloatVector, + ) + + testBson( context, "subtype 0x09 Vector FLOAT32", @@ -266,6 +277,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", FloatVector(127f, 7f)) }, + serialize(V(FloatVector(127f, 7f))), + serialize(VFloat(FloatVector(127f, 7f))), hex("170000000578000A0000000927000000FE420000E04000"), json($$"""{"x": {"$binary": {"base64": "JwAAAP5CAADgQA==", "subType": "09"}}}"""), verify("Read type") { @@ -288,6 +301,11 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { }, ) + @Serializable + data class VByte( + val x: ByteVector, + ) + testBson( context, "subtype 0x09 Vector INT8", @@ -300,6 +318,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", ByteVector(127, 7)) }, + serialize(V(ByteVector(127, 7))), + serialize(VByte(ByteVector(127, 7))), hex("11000000057800040000000903007F0700"), json($$"""{"x": {"$binary": {"base64": "AwB/Bw==", "subType": "09"}}}"""), verify("Read type") { @@ -322,6 +342,11 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { }, ) + @Serializable + data class VBoolean( + val x: BooleanVector, + ) + testBson( context, "subtype 0x09 Vector PACKED_BIT", @@ -334,6 +359,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", BooleanVector(true, true, true, true, true, true, true, false, true, true, true, false, false, false, false, false)) }, + serialize(V(BooleanVector(true, true, true, true, true, true, true, false, true, true, true, false, false, false, false, false))), + serialize(VBoolean(BooleanVector(true, true, true, true, true, true, true, false, true, true, true, false, false, false, false, false))), hex("11000000057800040000000910007F0700"), json($$"""{"x": {"$binary": {"base64": "EAB/Bw==", "subType": "09"}}}"""), verify("Read type") { @@ -368,6 +395,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", FloatVector()) }, + serialize(V(FloatVector())), + serialize(VFloat(FloatVector())), hex("0F0000000578000200000009270000"), json($$"""{"x": {"$binary": {"base64": "JwA=", "subType": "09"}}}"""), verify("Read type") { @@ -402,6 +431,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", ByteVector()) }, + serialize(V(ByteVector())), + serialize(VByte(ByteVector())), hex("0F0000000578000200000009030000"), json($$"""{"x": {"$binary": {"base64": "AwA=", "subType": "09"}}}"""), verify("Read type") { @@ -436,6 +467,8 @@ fun SuiteDsl.binary(context: Prepared) = suite("Binary") { document { writeVector("x", BooleanVector()) }, + serialize(V(BooleanVector())), + serialize(VBoolean(BooleanVector())), hex("0F0000000578000200000009100000"), json($$"""{"x": {"$binary": {"base64": "EAA=", "subType": "09"}}}"""), verify("Read type") {