From cee6c85b9895db3f49930b41f644e7696362d8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Sat, 28 Feb 2026 20:49:33 +0100 Subject: [PATCH] feat(bson-official): Support serialization of Vector subclasses --- .../src/jvmMain/kotlin/BsonContext.jvm.kt | 4 + .../src/jvmMain/kotlin/types/Vector.jvm.kt | 141 ++++++++++++++++++ .../SerializationOptionsCompatibility.kt | 46 +++++- .../src/jvmTest/kotlin/types/VectorJvmTest.kt | 55 +++++++ bson/src/commonMain/kotlin/types/Vector.kt | 99 ++++++++++++ bson/src/jvmMain/kotlin/types/Vector.jvm.kt | 46 ++++++ .../nativeMain/kotlin/types/Vector.native.kt | 26 ++++ .../kotlin/types/Vector.wasmWasi.kt | 26 ++++ bson/src/webMain/kotlin/types/Vector.web.kt | 26 ++++ 9 files changed, 461 insertions(+), 8 deletions(-) create mode 100644 bson-official/src/jvmMain/kotlin/types/Vector.jvm.kt create mode 100644 bson-official/src/jvmTest/kotlin/types/VectorJvmTest.kt create mode 100644 bson/src/jvmMain/kotlin/types/Vector.jvm.kt create mode 100644 bson/src/nativeMain/kotlin/types/Vector.native.kt create mode 100644 bson/src/wasmWasiMain/kotlin/types/Vector.wasmWasi.kt create mode 100644 bson/src/webMain/kotlin/types/Vector.web.kt diff --git a/bson-official/src/jvmMain/kotlin/BsonContext.jvm.kt b/bson-official/src/jvmMain/kotlin/BsonContext.jvm.kt index 2b92076d..e321ec50 100644 --- a/bson-official/src/jvmMain/kotlin/BsonContext.jvm.kt +++ b/bson-official/src/jvmMain/kotlin/BsonContext.jvm.kt @@ -109,6 +109,10 @@ private class JvmBsonFactoryImpl( KotlinTimestampCodec(), KotlinUuidCodec(), KotlinInstantCodec(), + KotlinVectorCodec(), + KotlinFloatVectorCodec(), + KotlinBooleanVectorCodec(), + KotlinByteVectorCodec(), ), codecRegistry, ) diff --git a/bson-official/src/jvmMain/kotlin/types/Vector.jvm.kt b/bson-official/src/jvmMain/kotlin/types/Vector.jvm.kt new file mode 100644 index 00000000..bcf2a2cf --- /dev/null +++ b/bson-official/src/jvmMain/kotlin/types/Vector.jvm.kt @@ -0,0 +1,141 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package opensavvy.ktmongo.bson.official.types + +import opensavvy.ktmongo.bson.types.BooleanVector +import opensavvy.ktmongo.bson.types.ByteVector +import opensavvy.ktmongo.bson.types.FloatVector +import opensavvy.ktmongo.bson.types.Vector +import opensavvy.ktmongo.dsl.LowLevelApi +import org.bson.* +import org.bson.codecs.Codec +import org.bson.codecs.DecoderContext +import org.bson.codecs.EncoderContext + +// region Conversions + +/** + * Converts a KtMongo [Vector] to an official [BsonBinary]. + */ +@OptIn(LowLevelApi::class) +fun Vector.toBinary(): BsonBinary = BsonBinary( + 0x9, + toBinaryData(), +) + +fun FloatVector.toOfficial(): Float32BinaryVector = + BinaryVector.floatVector(toArray()) + +@OptIn(LowLevelApi::class) +fun BooleanVector.toOfficial(): PackedBitBinaryVector = + BinaryVector.packedBitVector(this.raw, this.padding) + +fun ByteVector.toOfficial(): Int8BinaryVector = + BinaryVector.int8Vector(toArray()) + +/** + * Converts an official [BsonBinary] to a KtMongo [Vector]. + */ +@OptIn(LowLevelApi::class) +fun BsonBinary.toKtMongoVector(): Vector = + Vector.fromBinaryData(this.data) + +fun Float32BinaryVector.toKtMongo(): FloatVector = + FloatVector(data.asList()) + +@OptIn(LowLevelApi::class) +fun PackedBitBinaryVector.toKtMongo(): BooleanVector = + BooleanVector(this.data, this.padding) + +fun Int8BinaryVector.toKtMongo(): ByteVector = + ByteVector(data.asList()) + +// endregion +// region Codecs + +internal class KotlinVectorCodec : Codec { + + override fun getEncoderClass(): Class = + Vector::class.java + + override fun encode(writer: BsonWriter, value: Vector, context: EncoderContext) { + writer.writeBinaryData(value.toBinary()) + } + + override fun decode(reader: BsonReader, context: DecoderContext): Vector? { + return reader.readBinaryData()?.toKtMongoVector() + } +} + +internal class KotlinFloatVectorCodec : Codec { + + override fun getEncoderClass(): Class = + FloatVector::class.java + + override fun encode(writer: BsonWriter, value: FloatVector, context: EncoderContext) { + writer.writeBinaryData(value.toBinary()) + } + + override fun decode(reader: BsonReader, context: DecoderContext): FloatVector? { + val vector = reader.readBinaryData()?.toKtMongoVector() + ?: return null + + check(vector is FloatVector) { "Expected to decode a ${FloatVector::class}, but found a ${vector::class}: $vector" } + + return vector + } +} + +internal class KotlinBooleanVectorCodec : Codec { + + override fun getEncoderClass(): Class = + BooleanVector::class.java + + override fun encode(writer: BsonWriter, value: BooleanVector, context: EncoderContext) { + writer.writeBinaryData(value.toBinary()) + } + + override fun decode(reader: BsonReader, context: DecoderContext): BooleanVector? { + val vector = reader.readBinaryData()?.toKtMongoVector() + ?: return null + + check(vector is BooleanVector) { "Expected to decode a ${BooleanVector::class}, but found a ${vector::class}: $vector" } + + return vector + } +} + +internal class KotlinByteVectorCodec : Codec { + + override fun getEncoderClass(): Class = + ByteVector::class.java + + override fun encode(writer: BsonWriter, value: ByteVector, context: EncoderContext) { + writer.writeBinaryData(value.toBinary()) + } + + override fun decode(reader: BsonReader, context: DecoderContext): ByteVector? { + val vector = reader.readBinaryData()?.toKtMongoVector() + ?: return null + + check(vector is ByteVector) { "Expected to decode a ${ByteVector::class}, but found a ${vector::class}: $vector" } + + return vector + } +} + +// endregion diff --git a/bson-official/src/jvmTest/kotlin/SerializationOptionsCompatibility.kt b/bson-official/src/jvmTest/kotlin/SerializationOptionsCompatibility.kt index f38cf946..71d7f73c 100644 --- a/bson-official/src/jvmTest/kotlin/SerializationOptionsCompatibility.kt +++ b/bson-official/src/jvmTest/kotlin/SerializationOptionsCompatibility.kt @@ -23,11 +23,13 @@ import kotlinx.serialization.Serializable import opensavvy.ktmongo.bson.ExperimentalBsonDiffApi import opensavvy.ktmongo.bson.diff import opensavvy.ktmongo.bson.read -import opensavvy.ktmongo.bson.types.Timestamp +import opensavvy.ktmongo.bson.types.* +import opensavvy.ktmongo.bson.types.Vector import opensavvy.ktmongo.bson.write import opensavvy.ktmongo.dsl.LowLevelApi import opensavvy.prepared.runner.testballoon.preparedSuite import opensavvy.prepared.suite.prepared +import java.util.* import kotlin.time.ExperimentalTime import kotlin.time.Instant import kotlin.uuid.ExperimentalUuidApi @@ -36,8 +38,12 @@ import kotlin.uuid.ExperimentalUuidApi data class SerializableWithDataClass( val a: String, val b: org.bson.types.ObjectId, - val c: opensavvy.ktmongo.bson.types.ObjectId, + val c: ObjectId, val d: Timestamp, + val e: Vector, + val f: FloatVector, + val g: ByteVector, + val h: BooleanVector, ) // Not a data class: can only be serialized with :bson-kotlinx @@ -45,8 +51,12 @@ data class SerializableWithDataClass( class SerializableWithKxS( val a: String, val b: @Contextual org.bson.types.ObjectId, - val c: opensavvy.ktmongo.bson.types.ObjectId, + val c: ObjectId, val d: Timestamp, + val e: Vector, + val f: FloatVector, + val g: ByteVector, + val h: BooleanVector, ) { override fun equals(other: Any?): Boolean { if (this === other) return true @@ -56,6 +66,10 @@ class SerializableWithKxS( if (b != other.b) return false if (c != other.c) return false if (d != other.d) return false + if (e != other.e) return false + if (f != other.f) return false + if (g != other.g) return false + if (h != other.h) return false return true } @@ -65,11 +79,15 @@ class SerializableWithKxS( result = 31 * result + b.hashCode() result = 31 * result + c.hashCode() result = 31 * result + d.hashCode() + result = 31 * result + e.hashCode() + result = 31 * result + f.hashCode() + result = 31 * result + g.hashCode() + result = 31 * result + h.hashCode() return result } override fun toString(): String { - return "SerializableWithKxS(a='$a', b=$b, c=$c, d=$d)" + return "SerializableWithKxS(a='$a', b=$b, c=$c, d=$d, e=$e, f=$f, g=$g, h=$h)" } } @@ -79,9 +97,13 @@ val SerializationOptionsCompatibility by preparedSuite { val expectedBson by prepared { testContext().buildDocument { writeString("a", "Bob") - writeObjectId("b", opensavvy.ktmongo.bson.types.ObjectId("640180000000000000000000")) - writeObjectId("c", opensavvy.ktmongo.bson.types.ObjectId("640180000000000000000000")) + writeObjectId("b", ObjectId("640180000000000000000000")) + writeObjectId("c", ObjectId("640180000000000000000000")) writeTimestamp("d", Timestamp(Instant.parse("2023-03-01T00:00:00Z"), 12u)) + writeVector("e", Vector.fromBinaryData(Base64.getDecoder().decode("EAA="))) + writeVector("f", FloatVector(127f, 7f)) + writeVector("g", ByteVector(127, 7)) + writeVector("h", BooleanVector(true, false)) } } @@ -89,8 +111,12 @@ val SerializationOptionsCompatibility by preparedSuite { SerializableWithDataClass( a = "Bob", b = org.bson.types.ObjectId("640180000000000000000000"), - c = opensavvy.ktmongo.bson.types.ObjectId("640180000000000000000000"), + c = ObjectId("640180000000000000000000"), d = Timestamp(Instant.parse("2023-03-01T00:00:00Z"), 12u), + e = Vector.fromBinaryData(Base64.getDecoder().decode("EAA=")), + f = FloatVector(127f, 7f), + g = ByteVector(127, 7), + h = BooleanVector(true, false), ) } @@ -98,8 +124,12 @@ val SerializationOptionsCompatibility by preparedSuite { SerializableWithKxS( a = "Bob", b = org.bson.types.ObjectId("640180000000000000000000"), - c = opensavvy.ktmongo.bson.types.ObjectId("640180000000000000000000"), + c = ObjectId("640180000000000000000000"), d = Timestamp(Instant.parse("2023-03-01T00:00:00Z"), 12u), + e = Vector.fromBinaryData(Base64.getDecoder().decode("EAA=")), + f = FloatVector(127f, 7f), + g = ByteVector(127, 7), + h = BooleanVector(true, false), ) } diff --git a/bson-official/src/jvmTest/kotlin/types/VectorJvmTest.kt b/bson-official/src/jvmTest/kotlin/types/VectorJvmTest.kt new file mode 100644 index 00000000..bf260a63 --- /dev/null +++ b/bson-official/src/jvmTest/kotlin/types/VectorJvmTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(LowLevelApi::class) + +package opensavvy.ktmongo.bson.official.types + +import opensavvy.ktmongo.bson.types.BooleanVector +import opensavvy.ktmongo.bson.types.ByteVector +import opensavvy.ktmongo.bson.types.FloatVector +import opensavvy.ktmongo.bson.types.Vector +import opensavvy.ktmongo.dsl.LowLevelApi +import opensavvy.prepared.runner.testballoon.preparedSuite +import kotlin.io.encoding.Base64 + +val OfficialVectorJvmSuite by preparedSuite { + + test("Vector binary-data round-trip") { + val vector = Vector.fromBinaryData(Base64.encodeToByteArray("EAA=".toByteArray())) + + check(vector.toBinary().toKtMongoVector() == vector) + } + + test("FloatVector round-trip") { + val vector = FloatVector(127.0f, 7.2f, -19.5f, Float.NaN) + + check(vector.toOfficial().toKtMongo() == vector) + } + + test("BooleanVector round-trip") { + val vector = BooleanVector(true, true, false, false, false, true, false, false, false, true) + + check(vector.toOfficial().toKtMongo() == vector) + } + + test("ByteVector round-trip") { + val vector = ByteVector(1, -1, 127, 13, 0, 99) + + check(vector.toOfficial().toKtMongo() == vector) + } + +} diff --git a/bson/src/commonMain/kotlin/types/Vector.kt b/bson/src/commonMain/kotlin/types/Vector.kt index f74bfca0..5722cf93 100644 --- a/bson/src/commonMain/kotlin/types/Vector.kt +++ b/bson/src/commonMain/kotlin/types/Vector.kt @@ -16,6 +16,13 @@ package opensavvy.ktmongo.bson.types +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import opensavvy.ktmongo.bson.BsonType import opensavvy.ktmongo.dsl.LowLevelApi import kotlin.experimental.or @@ -45,6 +52,7 @@ import kotlin.math.min * - [Atlas Vector Search](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-overview/) * - [Specification](https://github.com/mongodb/specifications/blob/master/source/bson-binary-vector/bson-binary-vector.md) */ +@Serializable(with = Vector.Serializer::class) interface Vector { /** @@ -107,6 +115,55 @@ interface Vector { else -> UnknownVector(content) } } + + /** + * Default serializer for [Vector]. + * + * When serializing into BSON, this serializer uses the efficient [`Vector`](https://bsonspec.org/spec.html#more-vector) binary subtype. + * + * When serializing to other formats (e.g. JSON…), this serializer uses a base64-encoded string. + * + * Avoid interacting with this type directly. + */ + @LowLevelApi + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = PrimitiveSerialDescriptor("opensavvy.ktmongo.bson.types.Vector", PrimitiveKind.STRING) + + override fun serialize(encoder: Encoder, value: Vector) { + serializeVectorPlatformSpecific(encoder, value) + } + + override fun deserialize(decoder: Decoder): Vector = + deserializeVectorPlatformSpecific(decoder) + } +} + +/** + * On the JVM, when using KotlinX.Serialization with the official driver, we must hard-code a different behavior. + * + * All non-JVM platforms implement this function by calling [serializeVectorAsString]. + * This could be simplified with [KT-20427](https://youtrack.jetbrains.com/projects/KT/issues/KT-20427). + */ +internal expect fun serializeVectorPlatformSpecific(encoder: Encoder, value: Vector) + +/** + * On the JVM, when using KotlinX.Serialization with the official driver, we must hard-code a different behavior. + * + * All non-JVM platforms implement this function by calling [deserializeVectorAsString]. + * This could be simplified with [KT-20427](https://youtrack.jetbrains.com/projects/KT/issues/KT-20427). + */ +internal expect fun deserializeVectorPlatformSpecific(decoder: Decoder): Vector + +@OptIn(LowLevelApi::class) +internal fun serializeVectorAsString(encoder: Encoder, value: Vector) { + encoder.encodeString(Base64.encode(value.toBinaryData())) +} + +@OptIn(LowLevelApi::class) +internal fun deserializeVectorAsString(decoder: Decoder): Vector { + val binaryData = Base64.decode(decoder.decodeString()) + return Vector.fromBinaryData(binaryData) } private class UnknownVector( @@ -168,6 +225,7 @@ private class UnknownVector( * Alternatively, this class implements [List]. */ @OptIn(LowLevelApi::class) +@Serializable(with = ByteVector.Serializer::class) class ByteVector internal constructor( /** * The underlying byte storage. **Do not mutate this array!** @@ -261,6 +319,19 @@ class ByteVector internal constructor( override fun toString(): String = joinToString(separator = ", ", prefix = "ByteVector[", postfix = "]") + + @LowLevelApi + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = Vector.serializer().descriptor + + override fun serialize(encoder: Encoder, value: ByteVector) { + encoder.encodeSerializableValue(Vector.serializer(), value) + } + + override fun deserialize(decoder: Decoder): ByteVector = + decoder.decodeSerializableValue(Vector.serializer()) as ByteVector + } } private fun floatsToBytes(floats: Collection): ByteArray { @@ -284,6 +355,7 @@ private fun floatsToBytes(floats: Collection): ByteArray { * * Alternatively, this class implements [List]. */ +@Serializable(with = FloatVector.Serializer::class) class FloatVector internal constructor( /** * The underlying byte storage. **Do not mutate this array!** @@ -445,6 +517,19 @@ class FloatVector internal constructor( override fun toString(): String = joinToString(separator = ", ", prefix = "FloatVector[", postfix = "]") + + @LowLevelApi + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = Vector.serializer().descriptor + + override fun serialize(encoder: Encoder, value: FloatVector) { + encoder.encodeSerializableValue(Vector.serializer(), value) + } + + override fun deserialize(decoder: Decoder): FloatVector = + decoder.decodeSerializableValue(Vector.serializer()) as FloatVector + } } private fun booleansToBytes(booleans: Collection): ByteArray { @@ -466,6 +551,7 @@ private fun booleansToBytes(booleans: Collection): ByteArray { * * Alternatively, this class implements [List]. */ +@Serializable(with = BooleanVector.Serializer::class) class BooleanVector internal constructor( /** * The underlying byte storage. **Do not mutate this array!** @@ -649,4 +735,17 @@ class BooleanVector internal constructor( override fun toString(): String = joinToString(separator = ", ", prefix = "BooleanVector[", postfix = "]") + + @LowLevelApi + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = Vector.serializer().descriptor + + override fun serialize(encoder: Encoder, value: BooleanVector) { + encoder.encodeSerializableValue(Vector.serializer(), value) + } + + override fun deserialize(decoder: Decoder): BooleanVector = + decoder.decodeSerializableValue(Vector.serializer()) as BooleanVector + } } diff --git a/bson/src/jvmMain/kotlin/types/Vector.jvm.kt b/bson/src/jvmMain/kotlin/types/Vector.jvm.kt new file mode 100644 index 00000000..69312fba --- /dev/null +++ b/bson/src/jvmMain/kotlin/types/Vector.jvm.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package opensavvy.ktmongo.bson.types + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import opensavvy.ktmongo.dsl.LowLevelApi +import org.bson.BsonBinary +import org.bson.BsonBinarySubType +import org.bson.codecs.kotlinx.BsonDecoder +import org.bson.codecs.kotlinx.BsonEncoder + +private val isOfficialKotlinSerializationEnabled = + ClassLoader.getSystemClassLoader().loadClass("org.bson.codecs.kotlinx.BsonEncoder") != null + +@OptIn(ExperimentalSerializationApi::class, LowLevelApi::class) +internal actual fun serializeVectorPlatformSpecific(encoder: Encoder, value: Vector) { + if (isOfficialKotlinSerializationEnabled && encoder is BsonEncoder) { + encoder.encodeBsonValue(BsonBinary(BsonBinarySubType.VECTOR, value.toBinaryData())) + } else { + serializeVectorAsString(encoder, value) + } +} + +@OptIn(ExperimentalSerializationApi::class, LowLevelApi::class) +internal actual fun deserializeVectorPlatformSpecific(decoder: Decoder): Vector = + if (isOfficialKotlinSerializationEnabled && decoder is BsonDecoder) { + val bsonBinary = decoder.decodeBsonValue() as BsonBinary + Vector.fromBinaryData(bsonBinary.data) + } else { + deserializeVectorAsString(decoder) + } diff --git a/bson/src/nativeMain/kotlin/types/Vector.native.kt b/bson/src/nativeMain/kotlin/types/Vector.native.kt new file mode 100644 index 00000000..a681cc6f --- /dev/null +++ b/bson/src/nativeMain/kotlin/types/Vector.native.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package opensavvy.ktmongo.bson.types + +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal actual fun serializeVectorPlatformSpecific(encoder: Encoder, value: Vector) { + serializeVectorAsString(encoder, value) +} + +internal actual fun deserializeVectorPlatformSpecific(decoder: Decoder): Vector = + deserializeVectorAsString(decoder) diff --git a/bson/src/wasmWasiMain/kotlin/types/Vector.wasmWasi.kt b/bson/src/wasmWasiMain/kotlin/types/Vector.wasmWasi.kt new file mode 100644 index 00000000..a681cc6f --- /dev/null +++ b/bson/src/wasmWasiMain/kotlin/types/Vector.wasmWasi.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package opensavvy.ktmongo.bson.types + +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal actual fun serializeVectorPlatformSpecific(encoder: Encoder, value: Vector) { + serializeVectorAsString(encoder, value) +} + +internal actual fun deserializeVectorPlatformSpecific(decoder: Decoder): Vector = + deserializeVectorAsString(decoder) diff --git a/bson/src/webMain/kotlin/types/Vector.web.kt b/bson/src/webMain/kotlin/types/Vector.web.kt new file mode 100644 index 00000000..a681cc6f --- /dev/null +++ b/bson/src/webMain/kotlin/types/Vector.web.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package opensavvy.ktmongo.bson.types + +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +internal actual fun serializeVectorPlatformSpecific(encoder: Encoder, value: Vector) { + serializeVectorAsString(encoder, value) +} + +internal actual fun deserializeVectorPlatformSpecific(decoder: Decoder): Vector = + deserializeVectorAsString(decoder) -- 2.51.2